diff --git a/Dockerfile b/Dockerfile index fd72e66..8a605bc 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,5 @@ # Use a rather old version of ubuntu to ensure compatibility regarding libc -FROM --platform=linux/amd64 debian:9 +FROM --platform=linux/amd64 ubuntu:20.04 LABEL description="Build environment for piutools" # Install build dependencies, multilib to get 32-bit versions @@ -19,6 +19,7 @@ RUN apt-get install -y libx11-dev:i386 RUN apt-get install -y libcurl4-gnutls-dev:i386 RUN apt-get install -y libglu1-mesa-dev:i386 RUN apt-get install -y libgl1:i386 +RUN apt-get install -y sudo # Delete apt-cache to reduce image size RUN rm -rf /var/lib/apt/lists/* @@ -27,4 +28,7 @@ RUN rm -rf /var/lib/apt/lists/* RUN mkdir /piutools WORKDIR /piutools -# docker build -t piutools_buildenv . \ No newline at end of file +COPY entrypoint.sh /entrypoint.sh +ENTRYPOINT ["/entrypoint.sh"] + +# docker build -t piutools_buildenv . diff --git a/Makefile b/Makefile index ed15421..7ffae76 100644 --- a/Makefile +++ b/Makefile @@ -17,12 +17,9 @@ all: $(BUILD_ROOT)/piutools.so plugins .PHONY: dist dist: - mkdir -p ./dist + mkdir -p ./dist/plugins cp -R ./ext/* ./dist/ - cp -R ./build/* ./dist/ - -$(BUILD_ROOT): - mkdir -p $@ + if [ -d ./build ]; then cp -R ./build/* ./dist/; fi .PHONY: piutools.so piutools.so: $(BUILD_ROOT)/piutools.so @@ -37,7 +34,7 @@ GENERIC_PLUGINS := asound ata_hdd ata_hdd_infinity eeprom exec_blocker fake_libu io_buttonboard io_mk5io io_mk6io locale lockchip \ network pit s3d_opengl sighandler statfix system_info \ ticket_dispenser -PLUGINS := ds1963s_in_ds2480b microdog stlfix usb_profile x11_keyboard_input $(GENERIC_PLUGINS) +PLUGINS := ds1963s_in_ds2480b pro1_data_zip microdog stlfix usb_profile x11_keyboard_input $(GENERIC_PLUGINS) PLUGIN_OBJS := $(patsubst %,$(PLUGIN_BUILD_ROOT)/%.plugin,$(PLUGINS)) .PHONY: plugins @@ -47,7 +44,7 @@ $(PLUGIN_BUILD_ROOT): mkdir -p $(PLUGIN_BUILD_ROOT) define generic_plugin_build -$(PLUGIN_BUILD_ROOT)/$(1).plugin: $$(wildcard src/plugins/$(1)/*.c) | $(PLUGIN_BUILD_ROOT) +$(PLUGIN_BUILD_ROOT)/$(1).plugin: $$(wildcard src/plugins/$(1)/*.c) | $(BUILD_ROOT) cc -shared -m32 -fPIC $(CFLAGS) $$^ $(PLUGIN_INCLUDES) -o $$@ endef @@ -82,7 +79,33 @@ DS1963S_IN_DS2480B_SOURCES := src/plugins/ds1963s_in_ds2480b/ds1963s_in_ds2480b. src/plugins/ds1963s_in_ds2480b/base64.c $(PLUGIN_BUILD_ROOT)/ds1963s_in_ds2480b.plugin: $(DS1963S_UTILS_SOURCES) $(DS1963S_IN_DS2480B_SOURCES) - cc -shared -m32 -fPIC $(CFLAGS) $(DS1963s_IN_DS2480B_SOURCES) $(DS1963S_UTILS_SOURCES) $(PLUGIN_INCLUDES) -lpthread -I src/plugins/ds1963s_in_ds2480b/ds1963s-utils/src -o $@ + cc -shared -m32 -fPIC $(CFLAGS) $(DS1963S_IN_DS2480B_SOURCES) $(DS1963S_UTILS_SOURCES) $(PLUGIN_INCLUDES) -lpthread -I src/plugins/ds1963s_in_ds2480b/ds1963s-utils/src -o $@ + +PRO1_DATA_ZIP_OW_SOURCES := src/plugins/pro1_data_zip/ow/crcutil.c \ + src/plugins/pro1_data_zip/ow/ds2480ut.c \ + src/plugins/pro1_data_zip/ow/linuxlnk.c \ + src/plugins/pro1_data_zip/ow/owerr.c \ + src/plugins/pro1_data_zip/ow/owllu.c \ + src/plugins/pro1_data_zip/ow/ownetu.c \ + src/plugins/pro1_data_zip/ow/owsesu.c \ + src/plugins/pro1_data_zip/ow/owtrnu.c \ + src/plugins/pro1_data_zip/ow/sha18.c \ + src/plugins/pro1_data_zip/ow/shaib.c + +PRO1_DATA_ZIP_SOURCES := src/plugins/pro1_data_zip/pro1_data_zip.c \ + src/plugins/pro1_data_zip/aes.c \ + src/plugins/pro1_data_zip/dongle.c \ + src/plugins/pro1_data_zip/enc_zip_file.c \ + src/plugins/pro1_data_zip/sig.c \ + src/plugins/pro1_data_zip/util.c + +#LTC_OBJS := src/plugins/pro1_data_zip/ltc/linux_x86/libtomcrypt.a \ +# src/plugins/pro1_data_zip/ltc/linux_x86/libtommath.a +LTC_OBJS := src/plugins/pro1_data_zip/ltc/linux_x86/libtomcrypt_debug.a \ + src/plugins/pro1_data_zip/ltc/linux_x86/libtommath.a + +$(PLUGIN_BUILD_ROOT)/pro1_data_zip.plugin: $(PRO1_DATA_ZIP_OW_SOURCES) $(PRO1_DATA_ZIP_SOURCES) $(LTC_OBJS) + cc -shared -m32 -fPIC $(CFLAGS) $(PRO1_DATA_ZIP_SOURCES) $(PRO1_DATA_ZIP_OW_SOURCES) $(LTC_OBJS) -I src/plugins/pro1_data_zip/ltc/headers $(PLUGIN_INCLUDES) -o $@ .PHONY: clean clean: diff --git a/build.sh b/build.sh new file mode 100755 index 0000000..93d482e --- /dev/null +++ b/build.sh @@ -0,0 +1,17 @@ +#!/usr/bin/env bash + +set -euo pipefail + +BUILDENV_IMG_NAME=${1:-piutools_buildenv} +BUILDENV_IMG_VERSION=${2:-latest} + +repo_name="${BUILDENV_IMG_NAME}:${BUILDENV_IMG_VERSION}" + +GID="$(id -g ${UID})" + +docker build -t ${repo_name} . +docker run --rm -v $PWD:/piutools \ + -e "CFLAGS=${CFLAGS:-""}" \ + -e "MY_UID=${UID}" \ + -e "MY_GID=${GID}" \ + ${repo_name} make diff --git a/entrypoint.sh b/entrypoint.sh new file mode 100755 index 0000000..9a854a3 --- /dev/null +++ b/entrypoint.sh @@ -0,0 +1,17 @@ +#!/usr/bin/env bash + +set -euo pipefail + +MY_UID="${MY_UID:-"0"}" +MY_GID="${MY_GID:-"0"}" + +# maintain permissions of calling user +if [ "x$MY_UID" != "x0" ]; then + groupadd -g $MY_GID somegroup + useradd -g $MY_UID someuser + echo "running as sudo ($MY_UID:$MY_GID): $@" + env + sudo --preserve-env=CFLAGS -g somegroup -u someuser "$@" +else + exec "$@" +fi diff --git a/ext/run_container.sh b/ext/run_container.sh old mode 100644 new mode 100755 index b47db40..36de0d3 --- a/ext/run_container.sh +++ b/ext/run_container.sh @@ -69,6 +69,7 @@ fi # Load Our Native Paths piutools_native_path=$(realpath $(pwd)) +piutools_native_src_path=$(realpath $piutools_native_path/../src) piutools_native_rom_path=$piutools_native_path/roms/$game_name piutools_native_config_path=$piutools_native_path/config/$game_name/$game_version.conf @@ -93,17 +94,25 @@ piutools_rom=$piutools_root/rom piutools_save=$piutools_root/save piutools_mnt=$piutools_root/mnt piutools_tmp=$piutools_root/tmp +piutools_src=$piutools_root/src #run_command= RUN_STRACE, RUN_GDB, RUN_GAME,RUN_LTRACE +img_name="${PIUTOOLS_CONTAINER_IMG_NAME:-"pumpos_classic"}" + docker_args="run --device /dev/fuse --cap-add SYS_ADMIN --rm -it" # Add the Graphics Support Stuff docker_args+=" --gpus all -v /tmp/.X11-unix:/tmp/.X11-unix -e DISPLAY=$DISPLAY" # Add the Sound Stuff -docker_args+=" -e PULSE_SERVER=$PULSE_SERVER -v /mnt/wslg/:/mnt/wslg/" +if [ -e /mnt/wslg ]; then + docker_args+=" -e PULSE_SERVER=$PULSE_SERVER -v /mnt/wslg/:/mnt/wslg/" +fi +# Allow ptrace (and disabling ASLR) for gdb and strace to work +docker_args+=" --cap-add=SYS_PTRACE --security-opt seccomp=unconfined" # Add Our PIUTools Mounts docker_args+=" -v $piutools_native_path:$piutools_bin" docker_args+=" -v $piutools_native_rom_path:$piutools_rom:ro" +docker_args+=" -v $piutools_native_src_path:$piutools_src:ro" docker_args+=" -v $piutools_native_save_path:$piutools_save" # Add Our PIUTools Envars docker_args+=" -e PIUTOOLS_GAME_NAME=$game_name" @@ -112,20 +121,22 @@ docker_args+=" -e PIUTOOLS_PATH=$piutools_bin" docker_args+=" -e PIUTOOLS_CONFIG_PATH=$piutools_config_path" docker_args+=" -e PIUTOOLS_PLUGIN_PATH=$piutools_plugins_path" docker_args+=" -e PIUTOOLS_ROM_PATH=$piutools_rom" +docker_args+=" -e PIUTOOLS_SRC_PATH=$piutools_src" docker_args+=" -e PIUTOOLS_SAVE_PATH=$piutools_save" docker_args+=" -e PIUTOOLS_TMP_PATH=$piutools_tmp" docker_args+=" -e PIUTOOLS_MNT_PATH=$piutools_mnt" +docker_args+=" -e PIUTOOLS_SRC_PATH=$piutools_src" docker_args+=" -e PIUTOOLS_ROMS=$game_roms" docker_args+=" -e PIUTOOLS_EXE_PATH=$exe_path" docker_args+=" -e PIUTOOLS_EXE_ARGS=$exe_args" docker_args+=" -e PIUTOOLS_GAME_DIR=$exe_game_dir" docker_args+=" -e PIUTOOLS_DEBUG=1" -docker_args+=" -e RUN_GAME=1" -#docker_args+=" -e RUN_GDB=1" -#docker_args+=" -e RUN_STRACE=1" -#docker_args+=" -e RUN_LTRACE=1" +docker_args+=" -e RUN_GAME=${RUN_GAME:-""}" +docker_args+=" -e RUN_GDB=${RUN_GDB:-""}" +docker_args+=" -e RUN_STRACE=${RUN_STRACE:-""}" +docker_args+=" -e RUN_LTRACE=${RUN_STRACE:-""}" -docker_args+=" pumpos_classic $piutools_bin/tools/bootstrap_game.sh" +docker_args+=" ${img_name} $piutools_bin/tools/bootstrap_game.sh" echo $docker_args diff --git a/ext/tools/bootstrap_game.sh b/ext/tools/bootstrap_game.sh index 12813fb..2fd0965 100644 --- a/ext/tools/bootstrap_game.sh +++ b/ext/tools/bootstrap_game.sh @@ -5,7 +5,7 @@ cat $PIUTOOLS_PATH/tools/pump_arrows.graphic #cat $PIUTOOLS_PATH/am.graphic #cat $PIUTOOLS_PATH/pumplogo.graphic # Set PIUTools Stuff -mkdir $PIUTOOLS_TMP_PATH +mkdir -p $PIUTOOLS_TMP_PATH # Read the list of gamedata roms and mount each. IFS=',' read -ra roms_array <<< "$PIUTOOLS_ROMS" @@ -71,4 +71,4 @@ elif [ -n "$RUN_GAME" ]; then else unset LD_PRELOAD exec /bin/bash -fi \ No newline at end of file +fi diff --git a/include/PIUTools_Hook.h b/include/PIUTools_Hook.h index 2ebc3d0..24fc459 100644 --- a/include/PIUTools_Hook.h +++ b/include/PIUTools_Hook.h @@ -23,8 +23,8 @@ typedef struct _HOOK_ENTRY { int PIUTools_Hook_GetFunctionAddress(const char* library_name, const char* function_name, void** pfunction_address); -void* PIUTools_Hook_Inline(const char* module_name, const char* function_name, void* hook_addr); -void* PIUTools_Hook_Import(const char* module_name, const char* library_name, const char* function_name, void* hook_addr); +void* PIUTools_Hook_Inline(const char* module_name, const char* function_name, void* hook_addr, const char *plugin_name); +void* PIUTools_Hook_Import(const char* module_name, const char* library_name, const char* function_name, void* hook_addr, const char *plugin_name); -typedef const PHookEntry (*plugin_init_t)(void); \ No newline at end of file +typedef const PHookEntry (*plugin_init_t)(void); diff --git a/include/PIUTools_Plugin.h b/include/PIUTools_Plugin.h index 5e8e0b9..4d2a586 100644 --- a/include/PIUTools_Plugin.h +++ b/include/PIUTools_Plugin.h @@ -1,4 +1,4 @@ #pragma once void PIUTools_Plugin_Init(void); -void PIUTools_Plugin_LoadHook(void* entry); \ No newline at end of file +void PIUTools_Plugin_LoadHook(void* entry, const char *plugin_name); diff --git a/src/core/PIUTools_Filesystem.c b/src/core/PIUTools_Filesystem.c index 51a647d..80e616e 100644 --- a/src/core/PIUTools_Filesystem.c +++ b/src/core/PIUTools_Filesystem.c @@ -115,7 +115,7 @@ void PIUTools_Filesystem_Redirect_Init(void){ PHookEntry fsredirect_entry = filesystem_redirect_entries; if (fsredirect_entry != NULL) { while (fsredirect_entry->hook_type != HOOK_ENTRY_END) { - PIUTools_Plugin_LoadHook(fsredirect_entry); + PIUTools_Plugin_LoadHook(fsredirect_entry, "filesystem_redirect"); // Move to the next entry fsredirect_entry++; } diff --git a/src/core/PIUTools_Hook.c b/src/core/PIUTools_Hook.c index f71a0eb..3b43332 100644 --- a/src/core/PIUTools_Hook.c +++ b/src/core/PIUTools_Hook.c @@ -37,7 +37,7 @@ static int piutools_hook_init(void){ return 1; } -static void print_hook_status(const char* hook_type, const char* module_name, const char* library_name, const char* function_name, int hook_status){ +static void print_hook_status(const char* hook_type, const char* plugin_name, const char* module_name, const char* library_name, const char* function_name, int hook_status){ const char* hook_fail_msg = "\033[1;31mHook Fail:\033[0m"; const char* hook_ok_msg = "\033[1;32mHook OK:\033[0m"; const char* hook_status_msg = (hook_status) ? hook_ok_msg:hook_fail_msg; @@ -45,14 +45,14 @@ static void print_hook_status(const char* hook_type, const char* module_name, co module_name = "Main Executable"; } - DBG_printf("[%s]: %s -- %s %s %s",hook_type,hook_status_msg, module_name, library_name, function_name); + DBG_printf("[plugin:%s][%s]: %s -- %s %s %s", plugin_name, hook_type, hook_status_msg, module_name, library_name, function_name); } int PIUTools_Hook_GetFunctionAddress(const char* library_name, const char* function_name, void** pfunction_address){ // If we didn't specify a place to store the function address, we can't do anything. if (pfunction_address == NULL) { + DBG_printf("[%s] (%s:%s) Error: pfunction_address cannot be NULL", __FUNCTION__, library_name, function_name); errno = EINVAL; - DBG_printf("[%s] Error: %s", __FUNCTION__, strerror(errno)); return 0; } @@ -60,16 +60,16 @@ int PIUTools_Hook_GetFunctionAddress(const char* library_name, const char* funct DBG_printf("[%s] %s:%s",__FUNCTION__,library_name,function_name); void* hLibrary = dlopen(library_name, RTLD_LAZY); if(hLibrary == NULL){ + DBG_printf("[%s] (%s:%s) Error: %s", __FUNCTION__, library_name, function_name, dlerror()); errno = EACCES; - DBG_printf("[%s] Error: %s", __FUNCTION__, strerror(errno)); return 0; } // Resolve our Symbol *pfunction_address = dlsym(hLibrary,function_name); // If we didn't resolve our symbol - die. if(*pfunction_address == NULL){ + DBG_printf("[%s] (%s:%s) Error: %s", __FUNCTION__, library_name, function_name, dlerror()); errno = EINVAL; - DBG_printf("[%s] Error: %s", __FUNCTION__, strerror(errno)); return 0; } @@ -78,16 +78,16 @@ int PIUTools_Hook_GetFunctionAddress(const char* library_name, const char* funct -void* PIUTools_Hook_Inline(const char* module_name, const char* function_name, void* hook_addr){ +void* PIUTools_Hook_Inline(const char* module_name, const char* function_name, void* hook_addr, const char *plugin_name){ if(!module_initialized){if(!piutools_hook_init()){exit(-1);}} void* res = hook_function_byname(module_name,function_name, hook_addr); - print_hook_status("HOOK_INLINE",module_name,"",function_name,(res != NULL)); + print_hook_status("HOOK_INLINE",plugin_name,module_name,"",function_name,(res != NULL)); return res; } -void* PIUTools_Hook_Import(const char* module_name, const char* library_name, const char* function_name, void* hook_addr){ +void* PIUTools_Hook_Import(const char* module_name, const char* library_name, const char* function_name, void* hook_addr, const char *plugin_name){ if(!module_initialized){if(!piutools_hook_init()){exit(-1);}} void* res = hook_import_byname(module_name,library_name,function_name,hook_addr); - print_hook_status("HOOK_IMPORT",module_name,library_name,function_name,(res != NULL)); + print_hook_status("HOOK_IMPORT",plugin_name,module_name,library_name,function_name,(res != NULL)); return res; } diff --git a/src/core/PIUTools_Plugin.c b/src/core/PIUTools_Plugin.c index d386dfe..23c5ebc 100644 --- a/src/core/PIUTools_Plugin.c +++ b/src/core/PIUTools_Plugin.c @@ -28,7 +28,7 @@ static void load_plugin(const char* plugin_name){ if (cur_entry != NULL) { while (cur_entry->hook_type != HOOK_ENTRY_END) { - PIUTools_Plugin_LoadHook((void*)cur_entry); + PIUTools_Plugin_LoadHook((void*)cur_entry, plugin_name); // Move to the next entry cur_entry++; } @@ -58,17 +58,17 @@ void PIUTools_Plugin_Init(void){ ini_parse(plugin_config_path,parse_loader_config,NULL); } -void PIUTools_Plugin_LoadHook(void* ventry){ +void PIUTools_Plugin_LoadHook(void* ventry, const char *plugin_name){ PHookEntry entry = (PHookEntry)ventry; if(!module_initialized){PIUTools_Plugin_Init();} if(entry->hook_enabled){ void* rfa; switch(entry->hook_type){ case HOOK_TYPE_INLINE: - rfa = PIUTools_Hook_Inline(entry->source_library_name,entry->target_function_name, entry->hook_function_addr); + rfa = PIUTools_Hook_Inline(entry->source_library_name,entry->target_function_name, entry->hook_function_addr, plugin_name); break; case HOOK_TYPE_IMPORT: - rfa = PIUTools_Hook_Import(entry->target_binary_name,entry->source_library_name,entry->target_function_name, entry->hook_function_addr); + rfa = PIUTools_Hook_Import(entry->target_binary_name,entry->source_library_name,entry->target_function_name, entry->hook_function_addr, plugin_name); break; default: break; @@ -77,4 +77,4 @@ void PIUTools_Plugin_LoadHook(void* ventry){ *entry->original_function_addr_ptr = rfa; } } -} \ No newline at end of file +} diff --git a/src/plugins/ds1963s_in_ds2480b/ds1963s_in_ds2480b.c b/src/plugins/ds1963s_in_ds2480b/ds1963s_in_ds2480b.c index 3e26a74..3133f53 100644 --- a/src/plugins/ds1963s_in_ds2480b/ds1963s_in_ds2480b.c +++ b/src/plugins/ds1963s_in_ds2480b/ds1963s_in_ds2480b.c @@ -22,26 +22,26 @@ /* file ops */ typedef int (*open_func_t)(const char *, int); -open_func_t next_open; +static open_func_t next_open; typedef int (*close_func_t)(int); -close_func_t next_close; +static close_func_t next_close; -int cur_fd = -1; +static int cur_fd = -1; static char *pathname; static struct ds2480b_device ds2480b; static struct ds1963s_device ds1963s; static struct transport *serial; -struct one_wire_bus bus; -pthread_t one_wire_thread; +static struct one_wire_bus bus; +static pthread_t one_wire_thread; // static data that should be populated in the ds1963s authenticated // data pages upon initialization #define DS1963S_NUM_AUTH_DATA_PAGES 16 #define DS1963S_AUTH_PAGE_SIZE 32 -char *static_auth_data_config_b64[DS1963S_NUM_AUTH_DATA_PAGES][128] = {0}; -uint8_t *auth_data_page_static_data[DS1963S_NUM_AUTH_DATA_PAGES] = {0}; +static char static_auth_data_config_b64[DS1963S_NUM_AUTH_DATA_PAGES][128] = {0}; +static uint8_t *auth_data_page_static_data[DS1963S_NUM_AUTH_DATA_PAGES] = {0}; -void *one_wire_loop() { +static void *one_wire_loop() { one_wire_bus_run(&bus); DBG_printf("%s: one-wire thread exited\n", __FUNCTION__); return NULL; @@ -58,10 +58,10 @@ int ds1963s_open(const char *path, int flags) { return next_open(path, flags); } -void _populate_auth_page_static_data(struct ds1963s_device *dev) { +static void _populate_auth_page_static_data(struct ds1963s_device *dev) { for (int i = 0; i < DS1963S_NUM_AUTH_DATA_PAGES; i++) { if (auth_data_page_static_data[i] != NULL) { - memcpy(&ds1963s_device->data_memory[i*32], auth_data_page_static_data[i], 32); + memcpy(&(ds1963s.data_memory[i*32]), auth_data_page_static_data[i], 32); } } } @@ -70,9 +70,11 @@ void _populate_auth_page_static_data(struct ds1963s_device *dev) { * converts base64 data and saves it as static data for the given auth * page */ -void _record_auth_page_static_data(int pagenum, char *data) { +static void _record_auth_page_static_data(int pagenum, char *data) { uint8_t *decoded_data = (uint8_t *)malloc(DS1963S_AUTH_PAGE_SIZE); base64_decode(data, strlen(data), decoded_data); + DBG_printf("[%s:%d] authpage%d: %s\n", __FILE__, __LINE__, pagenum, decoded_data); + auth_data_page_static_data[pagenum] = decoded_data; } int ds1963s_close(int fd) { @@ -173,7 +175,6 @@ const PHookEntry plugin_init(){ struct transport_pty_data *pdata; pdata = (struct transport_pty_data *)serial->private_data; pathname = pdata->pathname_slave; - PIUTools_Filesystem_AddRedirect(DEFAULT_SERIAL_DEVICE,pathname); DBG_printf("[%s] Fake ds1963s ready at %s\n", __FILE__, pathname); } @@ -189,5 +190,5 @@ const PHookEntry plugin_init(){ return NULL; } - return NULL; + return entries; } diff --git a/src/plugins/pro1_data_zip/aes.c b/src/plugins/pro1_data_zip/aes.c new file mode 100644 index 0000000..4481f7b --- /dev/null +++ b/src/plugins/pro1_data_zip/aes.c @@ -0,0 +1,572 @@ +/* + +This is an implementation of the AES algorithm, specifically ECB, CTR and CBC mode. +Block size can be chosen in aes.h - available choices are AES128, AES192, AES256. + +The implementation is verified against the test vectors in: + National Institute of Standards and Technology Special Publication 800-38A 2001 ED + +ECB-AES128 +---------- + + plain-text: + 6bc1bee22e409f96e93d7e117393172a + ae2d8a571e03ac9c9eb76fac45af8e51 + 30c81c46a35ce411e5fbc1191a0a52ef + f69f2445df4f9b17ad2b417be66c3710 + + key: + 2b7e151628aed2a6abf7158809cf4f3c + + resulting cipher + 3ad77bb40d7a3660a89ecaf32466ef97 + f5d3d58503b9699de785895a96fdbaaf + 43b1cd7f598ece23881b00e3ed030688 + 7b0c785e27e8ad3f8223207104725dd4 + + +NOTE: String length must be evenly divisible by 16byte (str_len % 16 == 0) + You should pad the end of the string with zeros if this is not the case. + For AES192/256 the key size is proportionally larger. + +*/ + + +/*****************************************************************************/ +/* Includes: */ +/*****************************************************************************/ +#include // CBC mode, for memset +#include "aes.h" + +/*****************************************************************************/ +/* Defines: */ +/*****************************************************************************/ +// The number of columns comprising a state in AES. This is a constant in AES. Value=4 +#define Nb 4 + +#if defined(AES256) && (AES256 == 1) + #define Nk 8 + #define Nr 14 +#elif defined(AES192) && (AES192 == 1) + #define Nk 6 + #define Nr 12 +#else + #define Nk 4 // The number of 32 bit words in a key. + #define Nr 10 // The number of rounds in AES Cipher. +#endif + +// jcallan@github points out that declaring Multiply as a function +// reduces code size considerably with the Keil ARM compiler. +// See this link for more information: https://github.com/kokke/tiny-AES-C/pull/3 +#ifndef MULTIPLY_AS_A_FUNCTION + #define MULTIPLY_AS_A_FUNCTION 0 +#endif + + + + +/*****************************************************************************/ +/* Private variables: */ +/*****************************************************************************/ +// state - array holding the intermediate results during decryption. +typedef uint8_t state_t[4][4]; + + + +// The lookup-tables are marked const so they can be placed in read-only storage instead of RAM +// The numbers below can be computed dynamically trading ROM for RAM - +// This can be useful in (embedded) bootloader applications, where ROM is often limited. +static const uint8_t sbox[256] = { + //0 1 2 3 4 5 6 7 8 9 A B C D E F + 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, + 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, + 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, + 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, + 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, + 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, + 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, + 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, + 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, + 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, + 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, + 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, + 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, + 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, + 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, + 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 }; + +#if (defined(CBC) && CBC == 1) || (defined(ECB) && ECB == 1) +static const uint8_t rsbox[256] = { + 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb, + 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, + 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e, + 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25, + 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92, + 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84, + 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06, + 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b, + 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73, + 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e, + 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, + 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4, + 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f, + 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef, + 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61, + 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d }; +#endif + +// The round constant word array, Rcon[i], contains the values given by +// x to the power (i-1) being powers of x (x is denoted as {02}) in the field GF(2^8) +static const uint8_t Rcon[11] = { + 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36 }; + +/* + * Jordan Goulder points out in PR #12 (https://github.com/kokke/tiny-AES-C/pull/12), + * that you can remove most of the elements in the Rcon array, because they are unused. + * + * From Wikipedia's article on the Rijndael key schedule @ https://en.wikipedia.org/wiki/Rijndael_key_schedule#Rcon + * + * "Only the first some of these constants are actually used – up to rcon[10] for AES-128 (as 11 round keys are needed), + * up to rcon[8] for AES-192, up to rcon[7] for AES-256. rcon[0] is not used in AES algorithm." + */ + + +/*****************************************************************************/ +/* Private functions: */ +/*****************************************************************************/ +/* +static uint8_t getSBoxValue(uint8_t num) +{ + return sbox[num]; +} +*/ +#define getSBoxValue(num) (sbox[(num)]) + +// This function produces Nb(Nr+1) round keys. The round keys are used in each round to decrypt the states. +static void KeyExpansion(uint8_t* RoundKey, const uint8_t* Key) +{ + unsigned i, j, k; + uint8_t tempa[4]; // Used for the column/row operations + + // The first round key is the key itself. + for (i = 0; i < Nk; ++i) + { + RoundKey[(i * 4) + 0] = Key[(i * 4) + 0]; + RoundKey[(i * 4) + 1] = Key[(i * 4) + 1]; + RoundKey[(i * 4) + 2] = Key[(i * 4) + 2]; + RoundKey[(i * 4) + 3] = Key[(i * 4) + 3]; + } + + // All other round keys are found from the previous round keys. + for (i = Nk; i < Nb * (Nr + 1); ++i) + { + { + k = (i - 1) * 4; + tempa[0]=RoundKey[k + 0]; + tempa[1]=RoundKey[k + 1]; + tempa[2]=RoundKey[k + 2]; + tempa[3]=RoundKey[k + 3]; + + } + + if (i % Nk == 0) + { + // This function shifts the 4 bytes in a word to the left once. + // [a0,a1,a2,a3] becomes [a1,a2,a3,a0] + + // Function RotWord() + { + const uint8_t u8tmp = tempa[0]; + tempa[0] = tempa[1]; + tempa[1] = tempa[2]; + tempa[2] = tempa[3]; + tempa[3] = u8tmp; + } + + // SubWord() is a function that takes a four-byte input word and + // applies the S-box to each of the four bytes to produce an output word. + + // Function Subword() + { + tempa[0] = getSBoxValue(tempa[0]); + tempa[1] = getSBoxValue(tempa[1]); + tempa[2] = getSBoxValue(tempa[2]); + tempa[3] = getSBoxValue(tempa[3]); + } + + tempa[0] = tempa[0] ^ Rcon[i/Nk]; + } +#if defined(AES256) && (AES256 == 1) + if (i % Nk == 4) + { + // Function Subword() + { + tempa[0] = getSBoxValue(tempa[0]); + tempa[1] = getSBoxValue(tempa[1]); + tempa[2] = getSBoxValue(tempa[2]); + tempa[3] = getSBoxValue(tempa[3]); + } + } +#endif + j = i * 4; k=(i - Nk) * 4; + RoundKey[j + 0] = RoundKey[k + 0] ^ tempa[0]; + RoundKey[j + 1] = RoundKey[k + 1] ^ tempa[1]; + RoundKey[j + 2] = RoundKey[k + 2] ^ tempa[2]; + RoundKey[j + 3] = RoundKey[k + 3] ^ tempa[3]; + } +} + +void AES_init_ctx(struct AES_ctx* ctx, const uint8_t* key) +{ + KeyExpansion(ctx->RoundKey, key); +} +#if (defined(CBC) && (CBC == 1)) || (defined(CTR) && (CTR == 1)) +void AES_init_ctx_iv(struct AES_ctx* ctx, const uint8_t* key, const uint8_t* iv) +{ + KeyExpansion(ctx->RoundKey, key); + memcpy (ctx->Iv, iv, AES_BLOCKLEN); +} +void AES_ctx_set_iv(struct AES_ctx* ctx, const uint8_t* iv) +{ + memcpy (ctx->Iv, iv, AES_BLOCKLEN); +} +#endif + +// This function adds the round key to state. +// The round key is added to the state by an XOR function. +static void AddRoundKey(uint8_t round, state_t* state, const uint8_t* RoundKey) +{ + uint8_t i,j; + for (i = 0; i < 4; ++i) + { + for (j = 0; j < 4; ++j) + { + (*state)[i][j] ^= RoundKey[(round * Nb * 4) + (i * Nb) + j]; + } + } +} + +// The SubBytes Function Substitutes the values in the +// state matrix with values in an S-box. +static void SubBytes(state_t* state) +{ + uint8_t i, j; + for (i = 0; i < 4; ++i) + { + for (j = 0; j < 4; ++j) + { + (*state)[j][i] = getSBoxValue((*state)[j][i]); + } + } +} + +// The ShiftRows() function shifts the rows in the state to the left. +// Each row is shifted with different offset. +// Offset = Row number. So the first row is not shifted. +static void ShiftRows(state_t* state) +{ + uint8_t temp; + + // Rotate first row 1 columns to left + temp = (*state)[0][1]; + (*state)[0][1] = (*state)[1][1]; + (*state)[1][1] = (*state)[2][1]; + (*state)[2][1] = (*state)[3][1]; + (*state)[3][1] = temp; + + // Rotate second row 2 columns to left + temp = (*state)[0][2]; + (*state)[0][2] = (*state)[2][2]; + (*state)[2][2] = temp; + + temp = (*state)[1][2]; + (*state)[1][2] = (*state)[3][2]; + (*state)[3][2] = temp; + + // Rotate third row 3 columns to left + temp = (*state)[0][3]; + (*state)[0][3] = (*state)[3][3]; + (*state)[3][3] = (*state)[2][3]; + (*state)[2][3] = (*state)[1][3]; + (*state)[1][3] = temp; +} + +static uint8_t xtime(uint8_t x) +{ + return ((x<<1) ^ (((x>>7) & 1) * 0x1b)); +} + +// MixColumns function mixes the columns of the state matrix +static void MixColumns(state_t* state) +{ + uint8_t i; + uint8_t Tmp, Tm, t; + for (i = 0; i < 4; ++i) + { + t = (*state)[i][0]; + Tmp = (*state)[i][0] ^ (*state)[i][1] ^ (*state)[i][2] ^ (*state)[i][3] ; + Tm = (*state)[i][0] ^ (*state)[i][1] ; Tm = xtime(Tm); (*state)[i][0] ^= Tm ^ Tmp ; + Tm = (*state)[i][1] ^ (*state)[i][2] ; Tm = xtime(Tm); (*state)[i][1] ^= Tm ^ Tmp ; + Tm = (*state)[i][2] ^ (*state)[i][3] ; Tm = xtime(Tm); (*state)[i][2] ^= Tm ^ Tmp ; + Tm = (*state)[i][3] ^ t ; Tm = xtime(Tm); (*state)[i][3] ^= Tm ^ Tmp ; + } +} + +// Multiply is used to multiply numbers in the field GF(2^8) +// Note: The last call to xtime() is unneeded, but often ends up generating a smaller binary +// The compiler seems to be able to vectorize the operation better this way. +// See https://github.com/kokke/tiny-AES-c/pull/34 +#if MULTIPLY_AS_A_FUNCTION +static uint8_t Multiply(uint8_t x, uint8_t y) +{ + return (((y & 1) * x) ^ + ((y>>1 & 1) * xtime(x)) ^ + ((y>>2 & 1) * xtime(xtime(x))) ^ + ((y>>3 & 1) * xtime(xtime(xtime(x)))) ^ + ((y>>4 & 1) * xtime(xtime(xtime(xtime(x)))))); /* this last call to xtime() can be omitted */ + } +#else +#define Multiply(x, y) \ + ( ((y & 1) * x) ^ \ + ((y>>1 & 1) * xtime(x)) ^ \ + ((y>>2 & 1) * xtime(xtime(x))) ^ \ + ((y>>3 & 1) * xtime(xtime(xtime(x)))) ^ \ + ((y>>4 & 1) * xtime(xtime(xtime(xtime(x)))))) \ + +#endif + +#if (defined(CBC) && CBC == 1) || (defined(ECB) && ECB == 1) +/* +static uint8_t getSBoxInvert(uint8_t num) +{ + return rsbox[num]; +} +*/ +#define getSBoxInvert(num) (rsbox[(num)]) + +// MixColumns function mixes the columns of the state matrix. +// The method used to multiply may be difficult to understand for the inexperienced. +// Please use the references to gain more information. +static void InvMixColumns(state_t* state) +{ + int i; + uint8_t a, b, c, d; + for (i = 0; i < 4; ++i) + { + a = (*state)[i][0]; + b = (*state)[i][1]; + c = (*state)[i][2]; + d = (*state)[i][3]; + + (*state)[i][0] = Multiply(a, 0x0e) ^ Multiply(b, 0x0b) ^ Multiply(c, 0x0d) ^ Multiply(d, 0x09); + (*state)[i][1] = Multiply(a, 0x09) ^ Multiply(b, 0x0e) ^ Multiply(c, 0x0b) ^ Multiply(d, 0x0d); + (*state)[i][2] = Multiply(a, 0x0d) ^ Multiply(b, 0x09) ^ Multiply(c, 0x0e) ^ Multiply(d, 0x0b); + (*state)[i][3] = Multiply(a, 0x0b) ^ Multiply(b, 0x0d) ^ Multiply(c, 0x09) ^ Multiply(d, 0x0e); + } +} + + +// The SubBytes Function Substitutes the values in the +// state matrix with values in an S-box. +static void InvSubBytes(state_t* state) +{ + uint8_t i, j; + for (i = 0; i < 4; ++i) + { + for (j = 0; j < 4; ++j) + { + (*state)[j][i] = getSBoxInvert((*state)[j][i]); + } + } +} + +static void InvShiftRows(state_t* state) +{ + uint8_t temp; + + // Rotate first row 1 columns to right + temp = (*state)[3][1]; + (*state)[3][1] = (*state)[2][1]; + (*state)[2][1] = (*state)[1][1]; + (*state)[1][1] = (*state)[0][1]; + (*state)[0][1] = temp; + + // Rotate second row 2 columns to right + temp = (*state)[0][2]; + (*state)[0][2] = (*state)[2][2]; + (*state)[2][2] = temp; + + temp = (*state)[1][2]; + (*state)[1][2] = (*state)[3][2]; + (*state)[3][2] = temp; + + // Rotate third row 3 columns to right + temp = (*state)[0][3]; + (*state)[0][3] = (*state)[1][3]; + (*state)[1][3] = (*state)[2][3]; + (*state)[2][3] = (*state)[3][3]; + (*state)[3][3] = temp; +} +#endif // #if (defined(CBC) && CBC == 1) || (defined(ECB) && ECB == 1) + +// Cipher is the main function that encrypts the PlainText. +static void Cipher(state_t* state, const uint8_t* RoundKey) +{ + uint8_t round = 0; + + // Add the First round key to the state before starting the rounds. + AddRoundKey(0, state, RoundKey); + + // There will be Nr rounds. + // The first Nr-1 rounds are identical. + // These Nr rounds are executed in the loop below. + // Last one without MixColumns() + for (round = 1; ; ++round) + { + SubBytes(state); + ShiftRows(state); + if (round == Nr) { + break; + } + MixColumns(state); + AddRoundKey(round, state, RoundKey); + } + // Add round key to last round + AddRoundKey(Nr, state, RoundKey); +} + +#if (defined(CBC) && CBC == 1) || (defined(ECB) && ECB == 1) +static void InvCipher(state_t* state, const uint8_t* RoundKey) +{ + uint8_t round = 0; + + // Add the First round key to the state before starting the rounds. + AddRoundKey(Nr, state, RoundKey); + + // There will be Nr rounds. + // The first Nr-1 rounds are identical. + // These Nr rounds are executed in the loop below. + // Last one without InvMixColumn() + for (round = (Nr - 1); ; --round) + { + InvShiftRows(state); + InvSubBytes(state); + AddRoundKey(round, state, RoundKey); + if (round == 0) { + break; + } + InvMixColumns(state); + } + +} +#endif // #if (defined(CBC) && CBC == 1) || (defined(ECB) && ECB == 1) + +/*****************************************************************************/ +/* Public functions: */ +/*****************************************************************************/ +#if defined(ECB) && (ECB == 1) + + +void AES_ECB_encrypt(const struct AES_ctx* ctx, uint8_t* buf) +{ + // The next function call encrypts the PlainText with the Key using AES algorithm. + Cipher((state_t*)buf, ctx->RoundKey); +} + +void AES_ECB_decrypt(const struct AES_ctx* ctx, uint8_t* buf) +{ + // The next function call decrypts the PlainText with the Key using AES algorithm. + InvCipher((state_t*)buf, ctx->RoundKey); +} + + +#endif // #if defined(ECB) && (ECB == 1) + + + + + +#if defined(CBC) && (CBC == 1) + + +static void XorWithIv(uint8_t* buf, const uint8_t* Iv) +{ + uint8_t i; + for (i = 0; i < AES_BLOCKLEN; ++i) // The block in AES is always 128bit no matter the key size + { + buf[i] ^= Iv[i]; + } +} + +void AES_CBC_encrypt_buffer(struct AES_ctx *ctx, uint8_t* buf, size_t length) +{ + size_t i; + uint8_t *Iv = ctx->Iv; + for (i = 0; i < length; i += AES_BLOCKLEN) + { + XorWithIv(buf, Iv); + Cipher((state_t*)buf, ctx->RoundKey); + Iv = buf; + buf += AES_BLOCKLEN; + } + /* store Iv in ctx for next call */ + memcpy(ctx->Iv, Iv, AES_BLOCKLEN); +} + +void AES_CBC_decrypt_buffer(struct AES_ctx* ctx, uint8_t* buf, size_t length) +{ + size_t i; + uint8_t storeNextIv[AES_BLOCKLEN]; + for (i = 0; i < length; i += AES_BLOCKLEN) + { + memcpy(storeNextIv, buf, AES_BLOCKLEN); + InvCipher((state_t*)buf, ctx->RoundKey); + XorWithIv(buf, ctx->Iv); + memcpy(ctx->Iv, storeNextIv, AES_BLOCKLEN); + buf += AES_BLOCKLEN; + } + +} + +#endif // #if defined(CBC) && (CBC == 1) + + + +#if defined(CTR) && (CTR == 1) + +/* Symmetrical operation: same function for encrypting as for decrypting. Note any IV/nonce should never be reused with the same key */ +void AES_CTR_xcrypt_buffer(struct AES_ctx* ctx, uint8_t* buf, size_t length) +{ + uint8_t buffer[AES_BLOCKLEN]; + + size_t i; + int bi; + for (i = 0, bi = AES_BLOCKLEN; i < length; ++i, ++bi) + { + if (bi == AES_BLOCKLEN) /* we need to regen xor compliment in buffer */ + { + + memcpy(buffer, ctx->Iv, AES_BLOCKLEN); + Cipher((state_t*)buffer,ctx->RoundKey); + + /* Increment Iv and handle overflow */ + for (bi = (AES_BLOCKLEN - 1); bi >= 0; --bi) + { + /* inc will overflow */ + if (ctx->Iv[bi] == 255) + { + ctx->Iv[bi] = 0; + continue; + } + ctx->Iv[bi] += 1; + break; + } + bi = 0; + } + + buf[i] = (buf[i] ^ buffer[bi]); + } +} + +#endif // #if defined(CTR) && (CTR == 1) + diff --git a/src/plugins/pro1_data_zip/aes.h b/src/plugins/pro1_data_zip/aes.h new file mode 100644 index 0000000..9c856e5 --- /dev/null +++ b/src/plugins/pro1_data_zip/aes.h @@ -0,0 +1,91 @@ +#ifndef _AES_H_ +#define _AES_H_ + +#include +#include + +// #define the macros below to 1/0 to enable/disable the mode of operation. +// +// CBC enables AES encryption in CBC-mode of operation. +// CTR enables encryption in counter-mode. +// ECB enables the basic ECB 16-byte block algorithm. All can be enabled simultaneously. + +// The #ifndef-guard allows it to be configured before #include'ing or at compile time. +#ifndef CBC + #define CBC 1 +#endif + +#ifndef ECB + #define ECB 1 +#endif + +#ifndef CTR + #define CTR 1 +#endif + + +//##define AES128 1 +#define AES192 1 +//#define AES256 1 + +#define AES_BLOCKLEN 16 // Block length in bytes - AES is 128b block only + +#if defined(AES256) && (AES256 == 1) + #define AES_KEYLEN 32 + #define AES_keyExpSize 240 +#elif defined(AES192) && (AES192 == 1) + #define AES_KEYLEN 24 + #define AES_keyExpSize 208 +#else + #define AES_KEYLEN 16 // Key length in bytes + #define AES_keyExpSize 176 +#endif + +struct AES_ctx +{ + uint8_t RoundKey[AES_keyExpSize]; +#if (defined(CBC) && (CBC == 1)) || (defined(CTR) && (CTR == 1)) + uint8_t Iv[AES_BLOCKLEN]; +#endif +}; + +void AES_init_ctx(struct AES_ctx* ctx, const uint8_t* key); +#if (defined(CBC) && (CBC == 1)) || (defined(CTR) && (CTR == 1)) +void AES_init_ctx_iv(struct AES_ctx* ctx, const uint8_t* key, const uint8_t* iv); +void AES_ctx_set_iv(struct AES_ctx* ctx, const uint8_t* iv); +#endif + +#if defined(ECB) && (ECB == 1) +// buffer size is exactly AES_BLOCKLEN bytes; +// you need only AES_init_ctx as IV is not used in ECB +// NB: ECB is considered insecure for most uses +void AES_ECB_encrypt(const struct AES_ctx* ctx, uint8_t* buf); +void AES_ECB_decrypt(const struct AES_ctx* ctx, uint8_t* buf); + +#endif // #if defined(ECB) && (ECB == !) + + +#if defined(CBC) && (CBC == 1) +// buffer size MUST be mutile of AES_BLOCKLEN; +// Suggest https://en.wikipedia.org/wiki/Padding_(cryptography)#PKCS7 for padding scheme +// NOTES: you need to set IV in ctx via AES_init_ctx_iv() or AES_ctx_set_iv() +// no IV should ever be reused with the same key +void AES_CBC_encrypt_buffer(struct AES_ctx* ctx, uint8_t* buf, size_t length); +void AES_CBC_decrypt_buffer(struct AES_ctx* ctx, uint8_t* buf, size_t length); + +#endif // #if defined(CBC) && (CBC == 1) + + +#if defined(CTR) && (CTR == 1) + +// Same function for encrypting as for decrypting. +// IV is incremented for every block, and used after encryption as XOR-compliment for output +// Suggesting https://en.wikipedia.org/wiki/Padding_(cryptography)#PKCS7 for padding scheme +// NOTES: you need to set IV in ctx with AES_init_ctx_iv() or AES_ctx_set_iv() +// no IV should ever be reused with the same key +void AES_CTR_xcrypt_buffer(struct AES_ctx* ctx, uint8_t* buf, size_t length); + +#endif // #if defined(CTR) && (CTR == 1) + + +#endif // _AES_H_ diff --git a/src/plugins/pro1_data_zip/dongle.c b/src/plugins/pro1_data_zip/dongle.c new file mode 100644 index 0000000..eb2c2c2 --- /dev/null +++ b/src/plugins/pro1_data_zip/dongle.c @@ -0,0 +1,71 @@ +// vim: set et sw=4 ts=4: +#include +#include "dongle.h" +#include "enc_zip_file.h" +#include "tomcrypt.h" +#include "ow/shaib.h" +#include "ow/ownet.h" +#include "PIUTools_Debug.h" + +int derive_aes_key_from_ds1963s(const enc_zip_file_header *h, uint8_t out[24]) { + uint8_t scratchpadWorkspace[60], sharesult[20]; + + hash_state key_seed, key_iter1, key_iter2; + sha1_init(&key_seed); + sha1_init(&key_iter1); + sha1_init(&key_iter2); + + // sha1(subkey), sha1(subkey+sha1(subkey)), sha1(subkey+sha1(subkey+sha1(subkey))) + sha1_process(&key_seed, h->subkey, 1024); + if (sha1_done(&key_seed, sharesult) != CRYPT_OK) { + fprintf(stderr, "%s: sha1_done failed\n", __FUNCTION__); + return -1; + } + memcpy(scratchpadWorkspace, sharesult, 20); + + sha1_process(&key_iter1, h->subkey, 1024); + sha1_process(&key_iter1, scratchpadWorkspace, 20); + if (sha1_done(&key_iter1, sharesult) != CRYPT_OK) { + fprintf(stderr, "%s: sha1_done failed\n", __FUNCTION__); + return -1; + } + memcpy(scratchpadWorkspace+20, sharesult, 20); + + sha1_process(&key_iter2, h->subkey, 1024); + sha1_process(&key_iter2, scratchpadWorkspace, 40); + if (sha1_done(&key_iter2, sharesult) != CRYPT_OK) { + fprintf(stderr, "%s: sha1_done failed\n", __FUNCTION__); + return -1; + } + memcpy(scratchpadWorkspace+40, sharesult, 20); + + return ds1963s_compute_data_sha(scratchpadWorkspace, out); +} + +int ds1963s_compute_data_sha(const uint8_t *input, uint8_t out[24]) { + uchar firstDataPage[32], firstScratchPad[32]; + SHACopr copr; + + memcpy(firstDataPage, input, 32); + + if ((copr.portnum = owAcquireEx("/dev/ttyS0")) == -1) { + // HACK: see if the 1963s_in_ds2480b plugin is already operable + if ((copr.portnum = owAcquireEx("/dev/pts/1")) == -1) { + DBG_printf("getKey(): failed to acquire port.\nCheck to see that:\n=== [stupid boxor dongle meme goes here]\n"); + return -1; + } + } + FindNewSHA(copr.portnum, copr.devAN, TRUE); + owSerialNum(copr.portnum, copr.devAN, FALSE); + WriteDataPageSHA18(copr.portnum, 0, firstDataPage, 0); + memset(firstScratchPad, '\0', 32); + memcpy(firstScratchPad+8, input+32, 15); + WriteScratchpadSHA18(copr.portnum, 0, firstScratchPad, 32, 1); + SHAFunction18(copr.portnum, SHA_SIGN_DATA_PAGE, 0, 1); + ReadScratchpadSHA18(copr.portnum, 0, 0, firstScratchPad, 1); + memset(firstDataPage, '\0', 32); + WriteDataPageSHA18(copr.portnum, 0, firstDataPage, 0); + owRelease(copr.portnum); + memcpy(out, firstScratchPad+8, 24); + return 0; +} diff --git a/src/plugins/pro1_data_zip/dongle.h b/src/plugins/pro1_data_zip/dongle.h new file mode 100644 index 0000000..b438193 --- /dev/null +++ b/src/plugins/pro1_data_zip/dongle.h @@ -0,0 +1,6 @@ +#pragma once +#include +#include "enc_zip_file.h" + +int derive_aes_key_from_ds1963s(const enc_zip_file_header *h, uint8_t out[24]); +int ds1963s_compute_data_sha(const uint8_t *input, uint8_t *out); diff --git a/src/plugins/pro1_data_zip/enc_zip_file.c b/src/plugins/pro1_data_zip/enc_zip_file.c new file mode 100644 index 0000000..e1f89c0 --- /dev/null +++ b/src/plugins/pro1_data_zip/enc_zip_file.c @@ -0,0 +1,29 @@ +#include +#include +#include +#include +#include +#include "PIUTools_Debug.h" +#include "enc_zip_file.h" +#include "util.h" + +enc_zip_file_header *generate_header(int fd) { + enc_zip_file_header *header = (enc_zip_file_header *)malloc(sizeof(enc_zip_file_header)); + if (header == NULL) { + perror("malloc()"); + return NULL; + } + + strncpy(header->magic, ">>", 2); + header->subkey_size = PRO1_SUBKEY_SIZE; + generate_random_bytes(header->subkey, PRO1_SUBKEY_SIZE); + generate_random_bytes(header->salt, PRO1_AES_BLOCK_SIZE); + + // get file size + off_t curpos; + curpos = lseek(fd, 0, SEEK_CUR); + header->file_size = lseek(fd, 0, SEEK_END); + lseek(fd, curpos, SEEK_SET); + + return header; +} diff --git a/src/plugins/pro1_data_zip/enc_zip_file.h b/src/plugins/pro1_data_zip/enc_zip_file.h new file mode 100644 index 0000000..bbbe3a2 --- /dev/null +++ b/src/plugins/pro1_data_zip/enc_zip_file.h @@ -0,0 +1,27 @@ +#ifndef ENC_ZIP_FILE_H +#define ENC_ZIP_FILE_H + +#include + +#define PRO1_SUBKEY_SIZE 1024 +#define PRO1_AES_BLOCK_SIZE 16 + +typedef struct __attribute__((__packed__)) enc_zip_file_header { + char magic[2]; // ">>" + uint32_t subkey_size; + uint8_t subkey[PRO1_SUBKEY_SIZE]; + + // encryption salt + uint8_t salt[PRO1_AES_BLOCK_SIZE]; + + // file size of the decrypted file + uint32_t file_size; + + // needs to start with "<<" when decrypted + uint8_t verify_block[PRO1_AES_BLOCK_SIZE]; +} enc_zip_file_header; + +enc_zip_file_header *generate_header(int fd); + + +#endif diff --git a/src/plugins/pro1_data_zip/hookdefs.h b/src/plugins/pro1_data_zip/hookdefs.h new file mode 100644 index 0000000..52f28f7 --- /dev/null +++ b/src/plugins/pro1_data_zip/hookdefs.h @@ -0,0 +1,8 @@ +#pragma once +#include +#include + +typedef int (*open_func_t)(const char *, int, ...); +typedef ssize_t (*read_func_t)(int, void *, size_t); +typedef int (*lseek_func_t)(int, off_t, int); +typedef int (*close_func_t)(int); diff --git a/src/plugins/pro1_data_zip/ltc/headers/tomcrypt.h b/src/plugins/pro1_data_zip/ltc/headers/tomcrypt.h new file mode 100644 index 0000000..fe96e5f --- /dev/null +++ b/src/plugins/pro1_data_zip/ltc/headers/tomcrypt.h @@ -0,0 +1,87 @@ +#ifndef TOMCRYPT_H_ +#define TOMCRYPT_H_ +#include +#include +#include +#include +#include +#include +#include + +/* use configuration data */ +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* version */ +#define CRYPT 0x0116 +#define SCRYPT "1.16" + +/* max size of either a cipher/hash block or symmetric key [largest of the two] */ +#define MAXBLOCKSIZE 128 + +/* descriptor table size */ +#define TAB_SIZE 32 + +/* error codes [will be expanded in future releases] */ +enum { + CRYPT_OK=0, /* Result OK */ + CRYPT_ERROR, /* Generic Error */ + CRYPT_NOP, /* Not a failure but no operation was performed */ + + CRYPT_INVALID_KEYSIZE, /* Invalid key size given */ + CRYPT_INVALID_ROUNDS, /* Invalid number of rounds */ + CRYPT_FAIL_TESTVECTOR, /* Algorithm failed test vectors */ + + CRYPT_BUFFER_OVERFLOW, /* Not enough space for output */ + CRYPT_INVALID_PACKET, /* Invalid input packet given */ + + CRYPT_INVALID_PRNGSIZE, /* Invalid number of bits for a PRNG */ + CRYPT_ERROR_READPRNG, /* Could not read enough from PRNG */ + + CRYPT_INVALID_CIPHER, /* Invalid cipher specified */ + CRYPT_INVALID_HASH, /* Invalid hash specified */ + CRYPT_INVALID_PRNG, /* Invalid PRNG specified */ + + CRYPT_MEM, /* Out of memory */ + + CRYPT_PK_TYPE_MISMATCH, /* Not equivalent types of PK keys */ + CRYPT_PK_NOT_PRIVATE, /* Requires a private PK key */ + + CRYPT_INVALID_ARG, /* Generic invalid argument */ + CRYPT_FILE_NOTFOUND, /* File Not Found */ + + CRYPT_PK_INVALID_TYPE, /* Invalid type of PK key */ + CRYPT_PK_INVALID_SYSTEM,/* Invalid PK system specified */ + CRYPT_PK_DUP, /* Duplicate key already in key ring */ + CRYPT_PK_NOT_FOUND, /* Key not found in keyring */ + CRYPT_PK_INVALID_SIZE, /* Invalid size input for PK parameters */ + + CRYPT_INVALID_PRIME_SIZE,/* Invalid size of prime requested */ + CRYPT_PK_INVALID_PADDING /* Invalid padding on input */ +}; + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus + } +#endif + +#endif /* TOMCRYPT_H_ */ + + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/plugins/pro1_data_zip/ltc/headers/tomcrypt_argchk.h b/src/plugins/pro1_data_zip/ltc/headers/tomcrypt_argchk.h new file mode 100644 index 0000000..c4014b8 --- /dev/null +++ b/src/plugins/pro1_data_zip/ltc/headers/tomcrypt_argchk.h @@ -0,0 +1,38 @@ +/* Defines the LTC_ARGCHK macro used within the library */ +/* ARGTYPE is defined in mycrypt_cfg.h */ +#if ARGTYPE == 0 + +#include + +/* this is the default LibTomCrypt macro */ +void crypt_argchk(char *v, char *s, int d); +#define LTC_ARGCHK(x) if (!(x)) { crypt_argchk(#x, __FILE__, __LINE__); } +#define LTC_ARGCHKVD(x) LTC_ARGCHK(x) + +#elif ARGTYPE == 1 + +/* fatal type of error */ +#define LTC_ARGCHK(x) assert((x)) +#define LTC_ARGCHKVD(x) LTC_ARGCHK(x) + +#elif ARGTYPE == 2 + +#define LTC_ARGCHK(x) if (!(x)) { fprintf(stderr, "\nwarning: ARGCHK failed at %s:%d\n", __FILE__, __LINE__); } +#define LTC_ARGCHKVD(x) LTC_ARGCHK(x) + +#elif ARGTYPE == 3 + +#define LTC_ARGCHK(x) +#define LTC_ARGCHKVD(x) LTC_ARGCHK(x) + +#elif ARGTYPE == 4 + +#define LTC_ARGCHK(x) if (!(x)) return CRYPT_INVALID_ARG; +#define LTC_ARGCHKVD(x) if (!(x)) return; + +#endif + + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/plugins/pro1_data_zip/ltc/headers/tomcrypt_cfg.h b/src/plugins/pro1_data_zip/ltc/headers/tomcrypt_cfg.h new file mode 100644 index 0000000..f7ad3cc --- /dev/null +++ b/src/plugins/pro1_data_zip/ltc/headers/tomcrypt_cfg.h @@ -0,0 +1,136 @@ +/* This is the build config file. + * + * With this you can setup what to inlcude/exclude automatically during any build. Just comment + * out the line that #define's the word for the thing you want to remove. phew! + */ + +#ifndef TOMCRYPT_CFG_H +#define TOMCRYPT_CFG_H + +#if defined(_WIN32) || defined(_MSC_VER) +#define LTC_CALL __cdecl +#else +#ifndef LTC_CALL + #define LTC_CALL +#endif +#endif + +#ifndef LTC_EXPORT +#define LTC_EXPORT +#endif + +/* certain platforms use macros for these, making the prototypes broken */ +#ifndef LTC_NO_PROTOTYPES + +/* you can change how memory allocation works ... */ +LTC_EXPORT void * LTC_CALL XMALLOC(size_t n); +LTC_EXPORT void * LTC_CALL XREALLOC(void *p, size_t n); +LTC_EXPORT void * LTC_CALL XCALLOC(size_t n, size_t s); +LTC_EXPORT void LTC_CALL XFREE(void *p); + +LTC_EXPORT void LTC_CALL XQSORT(void *base, size_t nmemb, size_t size, int(*compar)(const void *, const void *)); + + +/* change the clock function too */ +LTC_EXPORT clock_t LTC_CALL XCLOCK(void); + +/* various other functions */ +LTC_EXPORT void * LTC_CALL XMEMCPY(void *dest, const void *src, size_t n); +LTC_EXPORT int LTC_CALL XMEMCMP(const void *s1, const void *s2, size_t n); +LTC_EXPORT void * LTC_CALL XMEMSET(void *s, int c, size_t n); + +LTC_EXPORT int LTC_CALL XSTRCMP(const char *s1, const char *s2); + +#endif + +/* type of argument checking, 0=default, 1=fatal and 2=error+continue, 3=nothing */ +#ifndef ARGTYPE + #define ARGTYPE 0 +#endif + +/* Controls endianess and size of registers. Leave uncommented to get platform neutral [slower] code + * + * Note: in order to use the optimized macros your platform must support unaligned 32 and 64 bit read/writes. + * The x86 platforms allow this but some others [ARM for instance] do not. On those platforms you **MUST** + * use the portable [slower] macros. + */ + +/* detect x86-32 machines somewhat */ +#if !defined(__STRICT_ANSI__) && (defined(INTEL_CC) || (defined(_MSC_VER) && defined(WIN32)) || (defined(__GNUC__) && (defined(__DJGPP__) || defined(__CYGWIN__) || defined(__MINGW32__) || defined(__i386__)))) + #define ENDIAN_LITTLE + #define ENDIAN_32BITWORD + #define LTC_FAST + #define LTC_FAST_TYPE unsigned long +#endif + +/* detects MIPS R5900 processors (PS2) */ +#if (defined(__R5900) || defined(R5900) || defined(__R5900__)) && (defined(_mips) || defined(__mips__) || defined(mips)) + #define ENDIAN_LITTLE + #define ENDIAN_64BITWORD +#endif + +/* detect amd64 */ +#if !defined(__STRICT_ANSI__) && defined(__x86_64__) + #define ENDIAN_LITTLE + #define ENDIAN_64BITWORD + #define LTC_FAST + #define LTC_FAST_TYPE unsigned long +#endif + +/* detect PPC32 */ +#if !defined(__STRICT_ANSI__) && defined(LTC_PPC32) + #define ENDIAN_BIG + #define ENDIAN_32BITWORD + #define LTC_FAST + #define LTC_FAST_TYPE unsigned long +#endif + +/* detect sparc and sparc64 */ +#if defined(__sparc__) + #define ENDIAN_BIG + #if defined(__arch64__) + #define ENDIAN_64BITWORD + #else + #define ENDIAN_32BITWORD + #endif +#endif + + +#ifdef LTC_NO_FAST + #ifdef LTC_FAST + #undef LTC_FAST + #endif +#endif + +/* No asm is a quick way to disable anything "not portable" */ +#ifdef LTC_NO_ASM + #undef ENDIAN_LITTLE + #undef ENDIAN_BIG + #undef ENDIAN_32BITWORD + #undef ENDIAN_64BITWORD + #undef LTC_FAST + #undef LTC_FAST_TYPE + #define LTC_NO_ROLC + #define LTC_NO_BSWAP +#endif + +/* #define ENDIAN_LITTLE */ +/* #define ENDIAN_BIG */ + +/* #define ENDIAN_32BITWORD */ +/* #define ENDIAN_64BITWORD */ + +#if (defined(ENDIAN_BIG) || defined(ENDIAN_LITTLE)) && !(defined(ENDIAN_32BITWORD) || defined(ENDIAN_64BITWORD)) + #error You must specify a word size as well as endianess in tomcrypt_cfg.h +#endif + +#if !(defined(ENDIAN_BIG) || defined(ENDIAN_LITTLE)) + #define ENDIAN_NEUTRAL +#endif + +#endif + + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/plugins/pro1_data_zip/ltc/headers/tomcrypt_cipher.h b/src/plugins/pro1_data_zip/ltc/headers/tomcrypt_cipher.h new file mode 100644 index 0000000..41f62c3 --- /dev/null +++ b/src/plugins/pro1_data_zip/ltc/headers/tomcrypt_cipher.h @@ -0,0 +1,839 @@ +/* ---- SYMMETRIC KEY STUFF ----- + * + * We put each of the ciphers scheduled keys in their own structs then we put all of + * the key formats in one union. This makes the function prototypes easier to use. + */ +#ifdef BLOWFISH +struct blowfish_key { + ulong32 S[4][256]; + ulong32 K[18]; +}; +#endif + +#ifdef RC5 +struct rc5_key { + int rounds; + ulong32 K[50]; +}; +#endif + +#ifdef RC6 +struct rc6_key { + ulong32 K[44]; +}; +#endif + +#ifdef SAFERP +struct saferp_key { + unsigned char K[33][16]; + long rounds; +}; +#endif + +#ifdef RIJNDAEL +struct rijndael_key { + ulong32 eK[60], dK[60]; + int Nr; +}; +#endif + +#ifdef KSEED +struct kseed_key { + ulong32 K[32], dK[32]; +}; +#endif + +#ifdef LTC_KASUMI +struct kasumi_key { + ulong32 KLi1[8], KLi2[8], + KOi1[8], KOi2[8], KOi3[8], + KIi1[8], KIi2[8], KIi3[8]; +}; +#endif + +#ifdef XTEA +struct xtea_key { + unsigned long A[32], B[32]; +}; +#endif + +#ifdef TWOFISH +#ifndef TWOFISH_SMALL + struct twofish_key { + ulong32 S[4][256], K[40]; + }; +#else + struct twofish_key { + ulong32 K[40]; + unsigned char S[32], start; + }; +#endif +#endif + +#ifdef SAFER +#define SAFER_K64_DEFAULT_NOF_ROUNDS 6 +#define SAFER_K128_DEFAULT_NOF_ROUNDS 10 +#define SAFER_SK64_DEFAULT_NOF_ROUNDS 8 +#define SAFER_SK128_DEFAULT_NOF_ROUNDS 10 +#define SAFER_MAX_NOF_ROUNDS 13 +#define SAFER_BLOCK_LEN 8 +#define SAFER_KEY_LEN (1 + SAFER_BLOCK_LEN * (1 + 2 * SAFER_MAX_NOF_ROUNDS)) +typedef unsigned char safer_block_t[SAFER_BLOCK_LEN]; +typedef unsigned char safer_key_t[SAFER_KEY_LEN]; +struct safer_key { safer_key_t key; }; +#endif + +#ifdef RC2 +struct rc2_key { unsigned xkey[64]; }; +#endif + +#ifdef DES +struct des_key { + ulong32 ek[32], dk[32]; +}; + +struct des3_key { + ulong32 ek[3][32], dk[3][32]; +}; +#endif + +#ifdef CAST5 +struct cast5_key { + ulong32 K[32], keylen; +}; +#endif + +#ifdef NOEKEON +struct noekeon_key { + ulong32 K[4], dK[4]; +}; +#endif + +#ifdef SKIPJACK +struct skipjack_key { + unsigned char key[10]; +}; +#endif + +#ifdef KHAZAD +struct khazad_key { + ulong64 roundKeyEnc[8 + 1]; + ulong64 roundKeyDec[8 + 1]; +}; +#endif + +#ifdef ANUBIS +struct anubis_key { + int keyBits; + int R; + ulong32 roundKeyEnc[18 + 1][4]; + ulong32 roundKeyDec[18 + 1][4]; +}; +#endif + +typedef union Symmetric_key { +#ifdef DES + struct des_key des; + struct des3_key des3; +#endif +#ifdef RC2 + struct rc2_key rc2; +#endif +#ifdef SAFER + struct safer_key safer; +#endif +#ifdef TWOFISH + struct twofish_key twofish; +#endif +#ifdef BLOWFISH + struct blowfish_key blowfish; +#endif +#ifdef RC5 + struct rc5_key rc5; +#endif +#ifdef RC6 + struct rc6_key rc6; +#endif +#ifdef SAFERP + struct saferp_key saferp; +#endif +#ifdef RIJNDAEL + struct rijndael_key rijndael; +#endif +#ifdef XTEA + struct xtea_key xtea; +#endif +#ifdef CAST5 + struct cast5_key cast5; +#endif +#ifdef NOEKEON + struct noekeon_key noekeon; +#endif +#ifdef SKIPJACK + struct skipjack_key skipjack; +#endif +#ifdef KHAZAD + struct khazad_key khazad; +#endif +#ifdef ANUBIS + struct anubis_key anubis; +#endif +#ifdef KSEED + struct kseed_key kseed; +#endif +#ifdef LTC_KASUMI + struct kasumi_key kasumi; +#endif + void *data; +} symmetric_key; + +#ifdef LTC_ECB_MODE +/** A block cipher ECB structure */ +typedef struct { + /** The index of the cipher chosen */ + int cipher, + /** The block size of the given cipher */ + blocklen; + /** The scheduled key */ + symmetric_key key; +} symmetric_ECB; +#endif + +#ifdef LTC_CFB_MODE +/** A block cipher CFB structure */ +typedef struct { + /** The index of the cipher chosen */ + int cipher, + /** The block size of the given cipher */ + blocklen, + /** The padding offset */ + padlen; + /** The current IV */ + unsigned char IV[MAXBLOCKSIZE], + /** The pad used to encrypt/decrypt */ + pad[MAXBLOCKSIZE]; + /** The scheduled key */ + symmetric_key key; +} symmetric_CFB; +#endif + +#ifdef LTC_OFB_MODE +/** A block cipher OFB structure */ +typedef struct { + /** The index of the cipher chosen */ + int cipher, + /** The block size of the given cipher */ + blocklen, + /** The padding offset */ + padlen; + /** The current IV */ + unsigned char IV[MAXBLOCKSIZE]; + /** The scheduled key */ + symmetric_key key; +} symmetric_OFB; +#endif + +#ifdef LTC_CBC_MODE +/** A block cipher CBC structure */ +typedef struct { + /** The index of the cipher chosen */ + int cipher, + /** The block size of the given cipher */ + blocklen; + /** The current IV */ + unsigned char IV[MAXBLOCKSIZE]; + /** The scheduled key */ + symmetric_key key; +} symmetric_CBC; +#endif + + +#ifdef LTC_CTR_MODE +/** A block cipher CTR structure */ +typedef struct { + /** The index of the cipher chosen */ + int cipher, + /** The block size of the given cipher */ + blocklen, + /** The padding offset */ + padlen, + /** The mode (endianess) of the CTR, 0==little, 1==big */ + mode; + /** The counter */ + unsigned char ctr[MAXBLOCKSIZE], + /** The pad used to encrypt/decrypt */ + pad[MAXBLOCKSIZE]; + /** The scheduled key */ + symmetric_key key; +} symmetric_CTR; +#endif + + +#ifdef LTC_LRW_MODE +/** A LRW structure */ +typedef struct { + /** The index of the cipher chosen (must be a 128-bit block cipher) */ + int cipher; + + /** The current IV */ + unsigned char IV[16], + + /** the tweak key */ + tweak[16], + + /** The current pad, it's the product of the first 15 bytes against the tweak key */ + pad[16]; + + /** The scheduled symmetric key */ + symmetric_key key; + +#ifdef LRW_TABLES + /** The pre-computed multiplication table */ + unsigned char PC[16][256][16]; +#endif +} symmetric_LRW; +#endif + +#ifdef LTC_F8_MODE +/** A block cipher F8 structure */ +typedef struct { + /** The index of the cipher chosen */ + int cipher, + /** The block size of the given cipher */ + blocklen, + /** The padding offset */ + padlen; + /** The current IV */ + unsigned char IV[MAXBLOCKSIZE], + MIV[MAXBLOCKSIZE]; + /** Current block count */ + ulong32 blockcnt; + /** The scheduled key */ + symmetric_key key; +} symmetric_F8; +#endif + + +/** cipher descriptor table, last entry has "name == NULL" to mark the end of table */ +extern struct ltc_cipher_descriptor { + /** name of cipher */ + char *name; + /** internal ID */ + unsigned char ID; + /** min keysize (octets) */ + int min_key_length, + /** max keysize (octets) */ + max_key_length, + /** block size (octets) */ + block_length, + /** default number of rounds */ + default_rounds; + /** Setup the cipher + @param key The input symmetric key + @param keylen The length of the input key (octets) + @param num_rounds The requested number of rounds (0==default) + @param skey [out] The destination of the scheduled key + @return CRYPT_OK if successful + */ + int (*setup)(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); + /** Encrypt a block + @param pt The plaintext + @param ct [out] The ciphertext + @param skey The scheduled key + @return CRYPT_OK if successful + */ + int (*ecb_encrypt)(const unsigned char *pt, unsigned char *ct, symmetric_key *skey); + /** Decrypt a block + @param ct The ciphertext + @param pt [out] The plaintext + @param skey The scheduled key + @return CRYPT_OK if successful + */ + int (*ecb_decrypt)(const unsigned char *ct, unsigned char *pt, symmetric_key *skey); + /** Test the block cipher + @return CRYPT_OK if successful, CRYPT_NOP if self-testing has been disabled + */ + int (*test)(void); + + /** Terminate the context + @param skey The scheduled key + */ + void (*done)(symmetric_key *skey); + + /** Determine a key size + @param keysize [in/out] The size of the key desired and the suggested size + @return CRYPT_OK if successful + */ + int (*keysize)(int *keysize); + +/** Accelerators **/ + /** Accelerated ECB encryption + @param pt Plaintext + @param ct Ciphertext + @param blocks The number of complete blocks to process + @param skey The scheduled key context + @return CRYPT_OK if successful + */ + int (*accel_ecb_encrypt)(const unsigned char *pt, unsigned char *ct, unsigned long blocks, symmetric_key *skey); + + /** Accelerated ECB decryption + @param pt Plaintext + @param ct Ciphertext + @param blocks The number of complete blocks to process + @param skey The scheduled key context + @return CRYPT_OK if successful + */ + int (*accel_ecb_decrypt)(const unsigned char *ct, unsigned char *pt, unsigned long blocks, symmetric_key *skey); + + /** Accelerated CBC encryption + @param pt Plaintext + @param ct Ciphertext + @param blocks The number of complete blocks to process + @param IV The initial value (input/output) + @param skey The scheduled key context + @return CRYPT_OK if successful + */ + int (*accel_cbc_encrypt)(const unsigned char *pt, unsigned char *ct, unsigned long blocks, unsigned char *IV, symmetric_key *skey); + + /** Accelerated CBC decryption + @param pt Plaintext + @param ct Ciphertext + @param blocks The number of complete blocks to process + @param IV The initial value (input/output) + @param skey The scheduled key context + @return CRYPT_OK if successful + */ + int (*accel_cbc_decrypt)(const unsigned char *ct, unsigned char *pt, unsigned long blocks, unsigned char *IV, symmetric_key *skey); + + /** Accelerated CTR encryption + @param pt Plaintext + @param ct Ciphertext + @param blocks The number of complete blocks to process + @param IV The initial value (input/output) + @param mode little or big endian counter (mode=0 or mode=1) + @param skey The scheduled key context + @return CRYPT_OK if successful + */ + int (*accel_ctr_encrypt)(const unsigned char *pt, unsigned char *ct, unsigned long blocks, unsigned char *IV, int mode, symmetric_key *skey); + + /** Accelerated LRW + @param pt Plaintext + @param ct Ciphertext + @param blocks The number of complete blocks to process + @param IV The initial value (input/output) + @param tweak The LRW tweak + @param skey The scheduled key context + @return CRYPT_OK if successful + */ + int (*accel_lrw_encrypt)(const unsigned char *pt, unsigned char *ct, unsigned long blocks, unsigned char *IV, const unsigned char *tweak, symmetric_key *skey); + + /** Accelerated LRW + @param ct Ciphertext + @param pt Plaintext + @param blocks The number of complete blocks to process + @param IV The initial value (input/output) + @param tweak The LRW tweak + @param skey The scheduled key context + @return CRYPT_OK if successful + */ + int (*accel_lrw_decrypt)(const unsigned char *ct, unsigned char *pt, unsigned long blocks, unsigned char *IV, const unsigned char *tweak, symmetric_key *skey); + + /** Accelerated CCM packet (one-shot) + @param key The secret key to use + @param keylen The length of the secret key (octets) + @param uskey A previously scheduled key [optional can be NULL] + @param nonce The session nonce [use once] + @param noncelen The length of the nonce + @param header The header for the session + @param headerlen The length of the header (octets) + @param pt [out] The plaintext + @param ptlen The length of the plaintext (octets) + @param ct [out] The ciphertext + @param tag [out] The destination tag + @param taglen [in/out] The max size and resulting size of the authentication tag + @param direction Encrypt or Decrypt direction (0 or 1) + @return CRYPT_OK if successful + */ + int (*accel_ccm_memory)( + const unsigned char *key, unsigned long keylen, + symmetric_key *uskey, + const unsigned char *nonce, unsigned long noncelen, + const unsigned char *header, unsigned long headerlen, + unsigned char *pt, unsigned long ptlen, + unsigned char *ct, + unsigned char *tag, unsigned long *taglen, + int direction); + + /** Accelerated GCM packet (one shot) + @param key The secret key + @param keylen The length of the secret key + @param IV The initial vector + @param IVlen The length of the initial vector + @param adata The additional authentication data (header) + @param adatalen The length of the adata + @param pt The plaintext + @param ptlen The length of the plaintext (ciphertext length is the same) + @param ct The ciphertext + @param tag [out] The MAC tag + @param taglen [in/out] The MAC tag length + @param direction Encrypt or Decrypt mode (GCM_ENCRYPT or GCM_DECRYPT) + @return CRYPT_OK on success + */ + int (*accel_gcm_memory)( + const unsigned char *key, unsigned long keylen, + const unsigned char *IV, unsigned long IVlen, + const unsigned char *adata, unsigned long adatalen, + unsigned char *pt, unsigned long ptlen, + unsigned char *ct, + unsigned char *tag, unsigned long *taglen, + int direction); + + /** Accelerated one shot OMAC + @param key The secret key + @param keylen The key length (octets) + @param in The message + @param inlen Length of message (octets) + @param out [out] Destination for tag + @param outlen [in/out] Initial and final size of out + @return CRYPT_OK on success + */ + int (*omac_memory)( + const unsigned char *key, unsigned long keylen, + const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen); + + /** Accelerated one shot XCBC + @param key The secret key + @param keylen The key length (octets) + @param in The message + @param inlen Length of message (octets) + @param out [out] Destination for tag + @param outlen [in/out] Initial and final size of out + @return CRYPT_OK on success + */ + int (*xcbc_memory)( + const unsigned char *key, unsigned long keylen, + const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen); + + /** Accelerated one shot F9 + @param key The secret key + @param keylen The key length (octets) + @param in The message + @param inlen Length of message (octets) + @param out [out] Destination for tag + @param outlen [in/out] Initial and final size of out + @return CRYPT_OK on success + @remark Requires manual padding + */ + int (*f9_memory)( + const unsigned char *key, unsigned long keylen, + const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen); +} cipher_descriptor[]; + +#ifdef BLOWFISH +int blowfish_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); +int blowfish_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey); +int blowfish_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey); +int blowfish_test(void); +void blowfish_done(symmetric_key *skey); +int blowfish_keysize(int *keysize); +extern const struct ltc_cipher_descriptor blowfish_desc; +#endif + +#ifdef RC5 +int rc5_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); +int rc5_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey); +int rc5_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey); +int rc5_test(void); +void rc5_done(symmetric_key *skey); +int rc5_keysize(int *keysize); +extern const struct ltc_cipher_descriptor rc5_desc; +#endif + +#ifdef RC6 +int rc6_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); +int rc6_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey); +int rc6_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey); +int rc6_test(void); +void rc6_done(symmetric_key *skey); +int rc6_keysize(int *keysize); +extern const struct ltc_cipher_descriptor rc6_desc; +#endif + +#ifdef RC2 +int rc2_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); +int rc2_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey); +int rc2_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey); +int rc2_test(void); +void rc2_done(symmetric_key *skey); +int rc2_keysize(int *keysize); +extern const struct ltc_cipher_descriptor rc2_desc; +#endif + +#ifdef SAFERP +int saferp_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); +int saferp_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey); +int saferp_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey); +int saferp_test(void); +void saferp_done(symmetric_key *skey); +int saferp_keysize(int *keysize); +extern const struct ltc_cipher_descriptor saferp_desc; +#endif + +#ifdef SAFER +int safer_k64_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); +int safer_sk64_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); +int safer_k128_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); +int safer_sk128_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); +int safer_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *key); +int safer_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *key); +int safer_k64_test(void); +int safer_sk64_test(void); +int safer_sk128_test(void); +void safer_done(symmetric_key *skey); +int safer_64_keysize(int *keysize); +int safer_128_keysize(int *keysize); +extern const struct ltc_cipher_descriptor safer_k64_desc, safer_k128_desc, safer_sk64_desc, safer_sk128_desc; +#endif + +#ifdef RIJNDAEL + +/* make aes an alias */ +#define aes_setup rijndael_setup +#define aes_ecb_encrypt rijndael_ecb_encrypt +#define aes_ecb_decrypt rijndael_ecb_decrypt +#define aes_test rijndael_test +#define aes_done rijndael_done +#define aes_keysize rijndael_keysize + +#define aes_enc_setup rijndael_enc_setup +#define aes_enc_ecb_encrypt rijndael_enc_ecb_encrypt +#define aes_enc_keysize rijndael_enc_keysize + +int rijndael_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); +int rijndael_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey); +int rijndael_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey); +int rijndael_test(void); +void rijndael_done(symmetric_key *skey); +int rijndael_keysize(int *keysize); +int rijndael_enc_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); +int rijndael_enc_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey); +void rijndael_enc_done(symmetric_key *skey); +int rijndael_enc_keysize(int *keysize); +extern const struct ltc_cipher_descriptor rijndael_desc, aes_desc; +extern const struct ltc_cipher_descriptor rijndael_enc_desc, aes_enc_desc; +#endif + +#ifdef XTEA +int xtea_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); +int xtea_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey); +int xtea_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey); +int xtea_test(void); +void xtea_done(symmetric_key *skey); +int xtea_keysize(int *keysize); +extern const struct ltc_cipher_descriptor xtea_desc; +#endif + +#ifdef TWOFISH +int twofish_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); +int twofish_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey); +int twofish_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey); +int twofish_test(void); +void twofish_done(symmetric_key *skey); +int twofish_keysize(int *keysize); +extern const struct ltc_cipher_descriptor twofish_desc; +#endif + +#ifdef DES +int des_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); +int des_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey); +int des_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey); +int des_test(void); +void des_done(symmetric_key *skey); +int des_keysize(int *keysize); +int des3_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); +int des3_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey); +int des3_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey); +int des3_test(void); +void des3_done(symmetric_key *skey); +int des3_keysize(int *keysize); +extern const struct ltc_cipher_descriptor des_desc, des3_desc; +#endif + +#ifdef CAST5 +int cast5_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); +int cast5_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey); +int cast5_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey); +int cast5_test(void); +void cast5_done(symmetric_key *skey); +int cast5_keysize(int *keysize); +extern const struct ltc_cipher_descriptor cast5_desc; +#endif + +#ifdef NOEKEON +int noekeon_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); +int noekeon_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey); +int noekeon_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey); +int noekeon_test(void); +void noekeon_done(symmetric_key *skey); +int noekeon_keysize(int *keysize); +extern const struct ltc_cipher_descriptor noekeon_desc; +#endif + +#ifdef SKIPJACK +int skipjack_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); +int skipjack_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey); +int skipjack_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey); +int skipjack_test(void); +void skipjack_done(symmetric_key *skey); +int skipjack_keysize(int *keysize); +extern const struct ltc_cipher_descriptor skipjack_desc; +#endif + +#ifdef KHAZAD +int khazad_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); +int khazad_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey); +int khazad_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey); +int khazad_test(void); +void khazad_done(symmetric_key *skey); +int khazad_keysize(int *keysize); +extern const struct ltc_cipher_descriptor khazad_desc; +#endif + +#ifdef ANUBIS +int anubis_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); +int anubis_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey); +int anubis_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey); +int anubis_test(void); +void anubis_done(symmetric_key *skey); +int anubis_keysize(int *keysize); +extern const struct ltc_cipher_descriptor anubis_desc; +#endif + +#ifdef KSEED +int kseed_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); +int kseed_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey); +int kseed_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey); +int kseed_test(void); +void kseed_done(symmetric_key *skey); +int kseed_keysize(int *keysize); +extern const struct ltc_cipher_descriptor kseed_desc; +#endif + +#ifdef LTC_KASUMI +int kasumi_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); +int kasumi_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey); +int kasumi_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey); +int kasumi_test(void); +void kasumi_done(symmetric_key *skey); +int kasumi_keysize(int *keysize); +extern const struct ltc_cipher_descriptor kasumi_desc; +#endif + +#ifdef LTC_ECB_MODE +int ecb_start(int cipher, const unsigned char *key, + int keylen, int num_rounds, symmetric_ECB *ecb); +int ecb_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_ECB *ecb); +int ecb_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_ECB *ecb); +int ecb_done(symmetric_ECB *ecb); +#endif + +#ifdef LTC_CFB_MODE +int cfb_start(int cipher, const unsigned char *IV, const unsigned char *key, + int keylen, int num_rounds, symmetric_CFB *cfb); +int cfb_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_CFB *cfb); +int cfb_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_CFB *cfb); +int cfb_getiv(unsigned char *IV, unsigned long *len, symmetric_CFB *cfb); +int cfb_setiv(const unsigned char *IV, unsigned long len, symmetric_CFB *cfb); +int cfb_done(symmetric_CFB *cfb); +#endif + +#ifdef LTC_OFB_MODE +int ofb_start(int cipher, const unsigned char *IV, const unsigned char *key, + int keylen, int num_rounds, symmetric_OFB *ofb); +int ofb_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_OFB *ofb); +int ofb_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_OFB *ofb); +int ofb_getiv(unsigned char *IV, unsigned long *len, symmetric_OFB *ofb); +int ofb_setiv(const unsigned char *IV, unsigned long len, symmetric_OFB *ofb); +int ofb_done(symmetric_OFB *ofb); +#endif + +#ifdef LTC_CBC_MODE +int cbc_start(int cipher, const unsigned char *IV, const unsigned char *key, + int keylen, int num_rounds, symmetric_CBC *cbc); +int cbc_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_CBC *cbc); +int cbc_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_CBC *cbc); +int cbc_getiv(unsigned char *IV, unsigned long *len, symmetric_CBC *cbc); +int cbc_setiv(const unsigned char *IV, unsigned long len, symmetric_CBC *cbc); +int cbc_done(symmetric_CBC *cbc); +#endif + +#ifdef LTC_CTR_MODE + +#define CTR_COUNTER_LITTLE_ENDIAN 0 +#define CTR_COUNTER_BIG_ENDIAN 1 +#define LTC_CTR_RFC3686 2 + +int ctr_start( int cipher, + const unsigned char *IV, + const unsigned char *key, int keylen, + int num_rounds, int ctr_mode, + symmetric_CTR *ctr); +int ctr_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_CTR *ctr); +int ctr_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_CTR *ctr); +int ctr_getiv(unsigned char *IV, unsigned long *len, symmetric_CTR *ctr); +int ctr_setiv(const unsigned char *IV, unsigned long len, symmetric_CTR *ctr); +int ctr_done(symmetric_CTR *ctr); +int ctr_test(void); +#endif + +#ifdef LTC_LRW_MODE + +#define LRW_ENCRYPT 0 +#define LRW_DECRYPT 1 + +int lrw_start( int cipher, + const unsigned char *IV, + const unsigned char *key, int keylen, + const unsigned char *tweak, + int num_rounds, + symmetric_LRW *lrw); +int lrw_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_LRW *lrw); +int lrw_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_LRW *lrw); +int lrw_getiv(unsigned char *IV, unsigned long *len, symmetric_LRW *lrw); +int lrw_setiv(const unsigned char *IV, unsigned long len, symmetric_LRW *lrw); +int lrw_done(symmetric_LRW *lrw); +int lrw_test(void); + +/* don't call */ +int lrw_process(const unsigned char *pt, unsigned char *ct, unsigned long len, int mode, symmetric_LRW *lrw); +#endif + +#ifdef LTC_F8_MODE +int f8_start( int cipher, const unsigned char *IV, + const unsigned char *key, int keylen, + const unsigned char *salt_key, int skeylen, + int num_rounds, symmetric_F8 *f8); +int f8_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_F8 *f8); +int f8_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_F8 *f8); +int f8_getiv(unsigned char *IV, unsigned long *len, symmetric_F8 *f8); +int f8_setiv(const unsigned char *IV, unsigned long len, symmetric_F8 *f8); +int f8_done(symmetric_F8 *f8); +int f8_test_mode(void); +#endif + + +int find_cipher(const char *name); +int find_cipher_any(const char *name, int blocklen, int keylen); +int find_cipher_id(unsigned char ID); +int register_cipher(const struct ltc_cipher_descriptor *cipher); +int unregister_cipher(const struct ltc_cipher_descriptor *cipher); +int cipher_is_valid(int idx); + +LTC_MUTEX_PROTO(ltc_cipher_mutex) + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/plugins/pro1_data_zip/ltc/headers/tomcrypt_custom.h b/src/plugins/pro1_data_zip/ltc/headers/tomcrypt_custom.h new file mode 100644 index 0000000..cf4be6d --- /dev/null +++ b/src/plugins/pro1_data_zip/ltc/headers/tomcrypt_custom.h @@ -0,0 +1,403 @@ +#ifndef TOMCRYPT_CUSTOM_H_ +#define TOMCRYPT_CUSTOM_H_ + +/* macros for various libc functions you can change for embedded targets */ +#ifndef XMALLOC + #ifdef malloc + #define LTC_NO_PROTOTYPES + #endif +#define XMALLOC malloc +#endif +#ifndef XREALLOC + #ifdef realloc + #define LTC_NO_PROTOTYPES + #endif +#define XREALLOC realloc +#endif +#ifndef XCALLOC + #ifdef calloc + #define LTC_NO_PROTOTYPES + #endif +#define XCALLOC calloc +#endif +#ifndef XFREE + #ifdef free + #define LTC_NO_PROTOTYPES + #endif +#define XFREE free +#endif + +#ifndef XMEMSET + #ifdef memset + #define LTC_NO_PROTOTYPES + #endif +#define XMEMSET memset +#endif +#ifndef XMEMCPY + #ifdef memcpy + #define LTC_NO_PROTOTYPES + #endif +#define XMEMCPY memcpy +#endif +#ifndef XMEMCMP + #ifdef memcmp + #define LTC_NO_PROTOTYPES + #endif +#define XMEMCMP memcmp +#endif +#ifndef XSTRCMP + #ifdef strcmp + #define LTC_NO_PROTOTYPES + #endif +#define XSTRCMP strcmp +#endif + +#ifndef XCLOCK +#define XCLOCK clock +#endif +#ifndef XCLOCKS_PER_SEC +#define XCLOCKS_PER_SEC CLOCKS_PER_SEC +#endif + +#ifndef XQSORT + #ifdef qsort + #define LTC_NO_PROTOTYPES + #endif +#define XQSORT qsort +#endif + +/* Easy button? */ +#ifdef LTC_EASY + #define LTC_NO_CIPHERS + #define RIJNDAEL + #define BLOWFISH + #define DES + #define CAST5 + + #define LTC_NO_MODES + #define LTC_ECB_MODE + #define LTC_CBC_MODE + #define LTC_CTR_MODE + + #define LTC_NO_HASHES + #define SHA1 + #define SHA512 + #define SHA384 + #define SHA256 + #define SHA224 + + #define LTC_NO_MACS + #define HMAC + #define OMAC + #define CCM_MODE + + #define LTC_NO_PRNGS + #define SPRNG + #define YARROW + #define DEVRANDOM + #define TRY_URANDOM_FIRST + + #define LTC_NO_PK + #define MRSA + #define MECC +#endif + +/* Use small code where possible */ +/* #define LTC_SMALL_CODE */ + +/* Enable self-test test vector checking */ +#ifndef LTC_NO_TEST + #define LTC_TEST +#endif + +/* clean the stack of functions which put private information on stack */ +/* #define LTC_CLEAN_STACK */ + +/* disable all file related functions */ +/* #define LTC_NO_FILE */ + +/* disable all forms of ASM */ +/* #define LTC_NO_ASM */ + +/* disable FAST mode */ +/* #define LTC_NO_FAST */ + +/* disable BSWAP on x86 */ +/* #define LTC_NO_BSWAP */ + +/* ---> Symmetric Block Ciphers <--- */ +#ifndef LTC_NO_CIPHERS + +#define BLOWFISH +#define RC2 +#define RC5 +#define RC6 +#define SAFERP +#define RIJNDAEL +#define XTEA +/* _TABLES tells it to use tables during setup, _SMALL means to use the smaller scheduled key format + * (saves 4KB of ram), _ALL_TABLES enables all tables during setup */ +#define TWOFISH +#ifndef LTC_NO_TABLES + #define TWOFISH_TABLES + /* #define TWOFISH_ALL_TABLES */ +#else + #define TWOFISH_SMALL +#endif +/* #define TWOFISH_SMALL */ +/* DES includes EDE triple-DES */ +#define DES +#define CAST5 +#define NOEKEON +#define SKIPJACK +#define SAFER +#define KHAZAD +#define ANUBIS +#define ANUBIS_TWEAK +#define KSEED +#define LTC_KASUMI + +#endif /* LTC_NO_CIPHERS */ + + +/* ---> Block Cipher Modes of Operation <--- */ +#ifndef LTC_NO_MODES + +#define LTC_CFB_MODE +#define LTC_OFB_MODE +#define LTC_ECB_MODE +#define LTC_CBC_MODE +#define LTC_CTR_MODE + +/* F8 chaining mode */ +#define LTC_F8_MODE + +/* LRW mode */ +#define LTC_LRW_MODE +#ifndef LTC_NO_TABLES + /* like GCM mode this will enable 16 8x128 tables [64KB] that make + * seeking very fast. + */ + #define LRW_TABLES +#endif + +#endif /* LTC_NO_MODES */ + +/* ---> One-Way Hash Functions <--- */ +#ifndef LTC_NO_HASHES + +#define CHC_HASH +#define WHIRLPOOL +#define SHA512 +#define SHA384 +#define SHA256 +#define SHA224 +#define TIGER +#define SHA1 +#define MD5 +#define MD4 +#define MD2 +#define RIPEMD128 +#define RIPEMD160 +#define RIPEMD256 +#define RIPEMD320 + +#endif /* LTC_NO_HASHES */ + +/* ---> MAC functions <--- */ +#ifndef LTC_NO_MACS + +#define LTC_HMAC +#define LTC_OMAC +#define LTC_PMAC +#define LTC_XCBC +#define LTC_F9_MODE +#define PELICAN + +#if defined(PELICAN) && !defined(RIJNDAEL) + #error Pelican-MAC requires RIJNDAEL +#endif + +/* ---> Encrypt + Authenticate Modes <--- */ + +#define EAX_MODE +#if defined(EAX_MODE) && !(defined(LTC_CTR_MODE) && defined(LTC_OMAC)) + #error EAX_MODE requires CTR and OMAC mode +#endif + +#define OCB_MODE +#define CCM_MODE +#define GCM_MODE + +/* Use 64KiB tables */ +#ifndef LTC_NO_TABLES + #define GCM_TABLES +#endif + +/* USE SSE2? requires GCC works on x86_32 and x86_64*/ +#ifdef GCM_TABLES +/* #define GCM_TABLES_SSE2 */ +#endif + +#endif /* LTC_NO_MACS */ + +/* Various tidbits of modern neatoness */ +#define BASE64 + +/* --> Pseudo Random Number Generators <--- */ +#ifndef LTC_NO_PRNGS + +/* Yarrow */ +#define YARROW +/* which descriptor of AES to use? */ +/* 0 = rijndael_enc 1 = aes_enc, 2 = rijndael [full], 3 = aes [full] */ +#define YARROW_AES 0 + +#if defined(YARROW) && !defined(LTC_CTR_MODE) + #error YARROW requires LTC_CTR_MODE chaining mode to be defined! +#endif + +/* a PRNG that simply reads from an available system source */ +#define SPRNG + +/* The RC4 stream cipher */ +#define RC4 + +/* Fortuna PRNG */ +#define FORTUNA +/* reseed every N calls to the read function */ +#define FORTUNA_WD 10 +/* number of pools (4..32) can save a bit of ram by lowering the count */ +#define FORTUNA_POOLS 32 + +/* Greg's SOBER128 PRNG ;-0 */ +#define SOBER128 + +/* the *nix style /dev/random device */ +#define DEVRANDOM +/* try /dev/urandom before trying /dev/random */ +#define TRY_URANDOM_FIRST + +#endif /* LTC_NO_PRNGS */ + +/* ---> math provider? <--- */ +#ifndef LTC_NO_MATH + +/* LibTomMath */ +/* #define LTM_DESC */ + +/* TomsFastMath */ +/* #define TFM_DESC */ + +#endif /* LTC_NO_MATH */ + +/* ---> Public Key Crypto <--- */ +#ifndef LTC_NO_PK + +/* Include RSA support */ +#define MRSA + +/* Include Katja (a Rabin variant like RSA) */ +/* #define MKAT */ + +/* Digital Signature Algorithm */ +#define MDSA + +/* ECC */ +#define MECC + +/* use Shamir's trick for point mul (speeds up signature verification) */ +#define LTC_ECC_SHAMIR + +#if defined(TFM_DESC) && defined(MECC) + #define MECC_ACCEL +#endif + +/* do we want fixed point ECC */ +/* #define MECC_FP */ + +/* Timing Resistant? */ +/* #define LTC_ECC_TIMING_RESISTANT */ + +#endif /* LTC_NO_PK */ + +/* PKCS #1 (RSA) and #5 (Password Handling) stuff */ +#ifndef LTC_NO_PKCS + +#define PKCS_1 +#define PKCS_5 + +/* Include ASN.1 DER (required by DSA/RSA) */ +#define LTC_DER + +#endif /* LTC_NO_PKCS */ + +/* cleanup */ + +#ifdef MECC +/* Supported ECC Key Sizes */ +#ifndef LTC_NO_CURVES + #define ECC112 + #define ECC128 + #define ECC160 + #define ECC192 + #define ECC224 + #define ECC256 + #define ECC384 + #define ECC521 +#endif +#endif + +#if defined(MECC) || defined(MRSA) || defined(MDSA) || defined(MKATJA) + /* Include the MPI functionality? (required by the PK algorithms) */ + #define MPI +#endif + +#ifdef MRSA + #define PKCS_1 +#endif + +#if defined(LTC_DER) && !defined(MPI) + #error ASN.1 DER requires MPI functionality +#endif + +#if (defined(MDSA) || defined(MRSA) || defined(MECC) || defined(MKATJA)) && !defined(LTC_DER) + #error PK requires ASN.1 DER functionality, make sure LTC_DER is enabled +#endif + +/* THREAD management */ +#ifdef LTC_PTHREAD + +#include + +#define LTC_MUTEX_GLOBAL(x) pthread_mutex_t x = PTHREAD_MUTEX_INITIALIZER; +#define LTC_MUTEX_PROTO(x) extern pthread_mutex_t x; +#define LTC_MUTEX_TYPE(x) pthread_mutex_t x; +#define LTC_MUTEX_INIT(x) pthread_mutex_init(x, NULL); +#define LTC_MUTEX_LOCK(x) pthread_mutex_lock(x); +#define LTC_MUTEX_UNLOCK(x) pthread_mutex_unlock(x); + +#else + +/* default no functions */ +#define LTC_MUTEX_GLOBAL(x) +#define LTC_MUTEX_PROTO(x) +#define LTC_MUTEX_TYPE(x) +#define LTC_MUTEX_INIT(x) +#define LTC_MUTEX_LOCK(x) +#define LTC_MUTEX_UNLOCK(x) + +#endif + +/* Debuggers */ + +/* define this if you use Valgrind, note: it CHANGES the way SOBER-128 and RC4 work (see the code) */ +/* #define LTC_VALGRIND */ + +#endif + + + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/plugins/pro1_data_zip/ltc/headers/tomcrypt_hash.h b/src/plugins/pro1_data_zip/ltc/headers/tomcrypt_hash.h new file mode 100644 index 0000000..a00aa4b --- /dev/null +++ b/src/plugins/pro1_data_zip/ltc/headers/tomcrypt_hash.h @@ -0,0 +1,379 @@ +/* ---- HASH FUNCTIONS ---- */ +#ifdef SHA512 +struct sha512_state { + ulong64 length, state[8]; + unsigned long curlen; + unsigned char buf[128]; +}; +#endif + +#ifdef SHA256 +struct sha256_state { + ulong64 length; + ulong32 state[8], curlen; + unsigned char buf[64]; +}; +#endif + +#ifdef SHA1 +struct sha1_state { + ulong64 length; + ulong32 state[5], curlen; + unsigned char buf[64]; +}; +#endif + +#ifdef MD5 +struct md5_state { + ulong64 length; + ulong32 state[4], curlen; + unsigned char buf[64]; +}; +#endif + +#ifdef MD4 +struct md4_state { + ulong64 length; + ulong32 state[4], curlen; + unsigned char buf[64]; +}; +#endif + +#ifdef TIGER +struct tiger_state { + ulong64 state[3], length; + unsigned long curlen; + unsigned char buf[64]; +}; +#endif + +#ifdef MD2 +struct md2_state { + unsigned char chksum[16], X[48], buf[16]; + unsigned long curlen; +}; +#endif + +#ifdef RIPEMD128 +struct rmd128_state { + ulong64 length; + unsigned char buf[64]; + ulong32 curlen, state[4]; +}; +#endif + +#ifdef RIPEMD160 +struct rmd160_state { + ulong64 length; + unsigned char buf[64]; + ulong32 curlen, state[5]; +}; +#endif + +#ifdef RIPEMD256 +struct rmd256_state { + ulong64 length; + unsigned char buf[64]; + ulong32 curlen, state[8]; +}; +#endif + +#ifdef RIPEMD320 +struct rmd320_state { + ulong64 length; + unsigned char buf[64]; + ulong32 curlen, state[10]; +}; +#endif + +#ifdef WHIRLPOOL +struct whirlpool_state { + ulong64 length, state[8]; + unsigned char buf[64]; + ulong32 curlen; +}; +#endif + +#ifdef CHC_HASH +struct chc_state { + ulong64 length; + unsigned char state[MAXBLOCKSIZE], buf[MAXBLOCKSIZE]; + ulong32 curlen; +}; +#endif + +typedef union Hash_state { + char dummy[1]; +#ifdef CHC_HASH + struct chc_state chc; +#endif +#ifdef WHIRLPOOL + struct whirlpool_state whirlpool; +#endif +#ifdef SHA512 + struct sha512_state sha512; +#endif +#ifdef SHA256 + struct sha256_state sha256; +#endif +#ifdef SHA1 + struct sha1_state sha1; +#endif +#ifdef MD5 + struct md5_state md5; +#endif +#ifdef MD4 + struct md4_state md4; +#endif +#ifdef MD2 + struct md2_state md2; +#endif +#ifdef TIGER + struct tiger_state tiger; +#endif +#ifdef RIPEMD128 + struct rmd128_state rmd128; +#endif +#ifdef RIPEMD160 + struct rmd160_state rmd160; +#endif +#ifdef RIPEMD256 + struct rmd256_state rmd256; +#endif +#ifdef RIPEMD320 + struct rmd320_state rmd320; +#endif + void *data; +} hash_state; + +/** hash descriptor */ +extern struct ltc_hash_descriptor { + /** name of hash */ + char *name; + /** internal ID */ + unsigned char ID; + /** Size of digest in octets */ + unsigned long hashsize; + /** Input block size in octets */ + unsigned long blocksize; + /** ASN.1 OID */ + unsigned long OID[16]; + /** Length of DER encoding */ + unsigned long OIDlen; + + /** Init a hash state + @param hash The hash to initialize + @return CRYPT_OK if successful + */ + int (*init)(hash_state *hash); + /** Process a block of data + @param hash The hash state + @param in The data to hash + @param inlen The length of the data (octets) + @return CRYPT_OK if successful + */ + int (*process)(hash_state *hash, const unsigned char *in, unsigned long inlen); + /** Produce the digest and store it + @param hash The hash state + @param out [out] The destination of the digest + @return CRYPT_OK if successful + */ + int (*done)(hash_state *hash, unsigned char *out); + /** Self-test + @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled + */ + int (*test)(void); + + /* accelerated hmac callback: if you need to-do multiple packets just use the generic hmac_memory and provide a hash callback */ + int (*hmac_block)(const unsigned char *key, unsigned long keylen, + const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen); + +} hash_descriptor[]; + +#ifdef CHC_HASH +int chc_register(int cipher); +int chc_init(hash_state * md); +int chc_process(hash_state * md, const unsigned char *in, unsigned long inlen); +int chc_done(hash_state * md, unsigned char *hash); +int chc_test(void); +extern const struct ltc_hash_descriptor chc_desc; +#endif + +#ifdef WHIRLPOOL +int whirlpool_init(hash_state * md); +int whirlpool_process(hash_state * md, const unsigned char *in, unsigned long inlen); +int whirlpool_done(hash_state * md, unsigned char *hash); +int whirlpool_test(void); +extern const struct ltc_hash_descriptor whirlpool_desc; +#endif + +#ifdef SHA512 +int sha512_init(hash_state * md); +int sha512_process(hash_state * md, const unsigned char *in, unsigned long inlen); +int sha512_done(hash_state * md, unsigned char *hash); +int sha512_test(void); +extern const struct ltc_hash_descriptor sha512_desc; +#endif + +#ifdef SHA384 +#ifndef SHA512 + #error SHA512 is required for SHA384 +#endif +int sha384_init(hash_state * md); +#define sha384_process sha512_process +int sha384_done(hash_state * md, unsigned char *hash); +int sha384_test(void); +extern const struct ltc_hash_descriptor sha384_desc; +#endif + +#ifdef SHA256 +int sha256_init(hash_state * md); +int sha256_process(hash_state * md, const unsigned char *in, unsigned long inlen); +int sha256_done(hash_state * md, unsigned char *hash); +int sha256_test(void); +extern const struct ltc_hash_descriptor sha256_desc; + +#ifdef SHA224 +#ifndef SHA256 + #error SHA256 is required for SHA224 +#endif +int sha224_init(hash_state * md); +#define sha224_process sha256_process +int sha224_done(hash_state * md, unsigned char *hash); +int sha224_test(void); +extern const struct ltc_hash_descriptor sha224_desc; +#endif +#endif + +#ifdef SHA1 +int sha1_init(hash_state * md); +int sha1_process(hash_state * md, const unsigned char *in, unsigned long inlen); +int sha1_done(hash_state * md, unsigned char *hash); +int sha1_test(void); +extern const struct ltc_hash_descriptor sha1_desc; +#endif + +#ifdef MD5 +int md5_init(hash_state * md); +int md5_process(hash_state * md, const unsigned char *in, unsigned long inlen); +int md5_done(hash_state * md, unsigned char *hash); +int md5_test(void); +extern const struct ltc_hash_descriptor md5_desc; +#endif + +#ifdef MD4 +int md4_init(hash_state * md); +int md4_process(hash_state * md, const unsigned char *in, unsigned long inlen); +int md4_done(hash_state * md, unsigned char *hash); +int md4_test(void); +extern const struct ltc_hash_descriptor md4_desc; +#endif + +#ifdef MD2 +int md2_init(hash_state * md); +int md2_process(hash_state * md, const unsigned char *in, unsigned long inlen); +int md2_done(hash_state * md, unsigned char *hash); +int md2_test(void); +extern const struct ltc_hash_descriptor md2_desc; +#endif + +#ifdef TIGER +int tiger_init(hash_state * md); +int tiger_process(hash_state * md, const unsigned char *in, unsigned long inlen); +int tiger_done(hash_state * md, unsigned char *hash); +int tiger_test(void); +extern const struct ltc_hash_descriptor tiger_desc; +#endif + +#ifdef RIPEMD128 +int rmd128_init(hash_state * md); +int rmd128_process(hash_state * md, const unsigned char *in, unsigned long inlen); +int rmd128_done(hash_state * md, unsigned char *hash); +int rmd128_test(void); +extern const struct ltc_hash_descriptor rmd128_desc; +#endif + +#ifdef RIPEMD160 +int rmd160_init(hash_state * md); +int rmd160_process(hash_state * md, const unsigned char *in, unsigned long inlen); +int rmd160_done(hash_state * md, unsigned char *hash); +int rmd160_test(void); +extern const struct ltc_hash_descriptor rmd160_desc; +#endif + +#ifdef RIPEMD256 +int rmd256_init(hash_state * md); +int rmd256_process(hash_state * md, const unsigned char *in, unsigned long inlen); +int rmd256_done(hash_state * md, unsigned char *hash); +int rmd256_test(void); +extern const struct ltc_hash_descriptor rmd256_desc; +#endif + +#ifdef RIPEMD320 +int rmd320_init(hash_state * md); +int rmd320_process(hash_state * md, const unsigned char *in, unsigned long inlen); +int rmd320_done(hash_state * md, unsigned char *hash); +int rmd320_test(void); +extern const struct ltc_hash_descriptor rmd320_desc; +#endif + + +int find_hash(const char *name); +int find_hash_id(unsigned char ID); +int find_hash_oid(const unsigned long *ID, unsigned long IDlen); +int find_hash_any(const char *name, int digestlen); +int register_hash(const struct ltc_hash_descriptor *hash); +int unregister_hash(const struct ltc_hash_descriptor *hash); +int hash_is_valid(int idx); + +LTC_MUTEX_PROTO(ltc_hash_mutex) + +int hash_memory(int hash, + const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen); +int hash_memory_multi(int hash, unsigned char *out, unsigned long *outlen, + const unsigned char *in, unsigned long inlen, ...); +int hash_filehandle(int hash, FILE *in, unsigned char *out, unsigned long *outlen); +int hash_file(int hash, const char *fname, unsigned char *out, unsigned long *outlen); + +/* a simple macro for making hash "process" functions */ +#define HASH_PROCESS(func_name, compress_name, state_var, block_size) \ +int func_name (hash_state * md, const unsigned char *in, unsigned long inlen) \ +{ \ + unsigned long n; \ + int err; \ + LTC_ARGCHK(md != NULL); \ + LTC_ARGCHK(in != NULL); \ + if (md-> state_var .curlen > sizeof(md-> state_var .buf)) { \ + return CRYPT_INVALID_ARG; \ + } \ + while (inlen > 0) { \ + if (md-> state_var .curlen == 0 && inlen >= block_size) { \ + if ((err = compress_name (md, (unsigned char *)in)) != CRYPT_OK) { \ + return err; \ + } \ + md-> state_var .length += block_size * 8; \ + in += block_size; \ + inlen -= block_size; \ + } else { \ + n = MIN(inlen, (block_size - md-> state_var .curlen)); \ + memcpy(md-> state_var .buf + md-> state_var.curlen, in, (size_t)n); \ + md-> state_var .curlen += n; \ + in += n; \ + inlen -= n; \ + if (md-> state_var .curlen == block_size) { \ + if ((err = compress_name (md, md-> state_var .buf)) != CRYPT_OK) { \ + return err; \ + } \ + md-> state_var .length += 8*block_size; \ + md-> state_var .curlen = 0; \ + } \ + } \ + } \ + return CRYPT_OK; \ +} + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/plugins/pro1_data_zip/ltc/headers/tomcrypt_mac.h b/src/plugins/pro1_data_zip/ltc/headers/tomcrypt_mac.h new file mode 100644 index 0000000..172c0d4 --- /dev/null +++ b/src/plugins/pro1_data_zip/ltc/headers/tomcrypt_mac.h @@ -0,0 +1,381 @@ +#ifdef LTC_HMAC +typedef struct Hmac_state { + hash_state md; + int hash; + hash_state hashstate; + unsigned char *key; +} hmac_state; + +int hmac_init(hmac_state *hmac, int hash, const unsigned char *key, unsigned long keylen); +int hmac_process(hmac_state *hmac, const unsigned char *in, unsigned long inlen); +int hmac_done(hmac_state *hmac, unsigned char *out, unsigned long *outlen); +int hmac_test(void); +int hmac_memory(int hash, + const unsigned char *key, unsigned long keylen, + const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen); +int hmac_memory_multi(int hash, + const unsigned char *key, unsigned long keylen, + unsigned char *out, unsigned long *outlen, + const unsigned char *in, unsigned long inlen, ...); +int hmac_file(int hash, const char *fname, const unsigned char *key, + unsigned long keylen, + unsigned char *dst, unsigned long *dstlen); +#endif + +#ifdef LTC_OMAC + +typedef struct { + int cipher_idx, + buflen, + blklen; + unsigned char block[MAXBLOCKSIZE], + prev[MAXBLOCKSIZE], + Lu[2][MAXBLOCKSIZE]; + symmetric_key key; +} omac_state; + +int omac_init(omac_state *omac, int cipher, const unsigned char *key, unsigned long keylen); +int omac_process(omac_state *omac, const unsigned char *in, unsigned long inlen); +int omac_done(omac_state *omac, unsigned char *out, unsigned long *outlen); +int omac_memory(int cipher, + const unsigned char *key, unsigned long keylen, + const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen); +int omac_memory_multi(int cipher, + const unsigned char *key, unsigned long keylen, + unsigned char *out, unsigned long *outlen, + const unsigned char *in, unsigned long inlen, ...); +int omac_file(int cipher, + const unsigned char *key, unsigned long keylen, + const char *filename, + unsigned char *out, unsigned long *outlen); +int omac_test(void); +#endif /* OMAC */ + +#ifdef LTC_PMAC + +typedef struct { + unsigned char Ls[32][MAXBLOCKSIZE], /* L shifted by i bits to the left */ + Li[MAXBLOCKSIZE], /* value of Li [current value, we calc from previous recall] */ + Lr[MAXBLOCKSIZE], /* L * x^-1 */ + block[MAXBLOCKSIZE], /* currently accumulated block */ + checksum[MAXBLOCKSIZE]; /* current checksum */ + + symmetric_key key; /* scheduled key for cipher */ + unsigned long block_index; /* index # for current block */ + int cipher_idx, /* cipher idx */ + block_len, /* length of block */ + buflen; /* number of bytes in the buffer */ +} pmac_state; + +int pmac_init(pmac_state *pmac, int cipher, const unsigned char *key, unsigned long keylen); +int pmac_process(pmac_state *pmac, const unsigned char *in, unsigned long inlen); +int pmac_done(pmac_state *pmac, unsigned char *out, unsigned long *outlen); + +int pmac_memory(int cipher, + const unsigned char *key, unsigned long keylen, + const unsigned char *msg, unsigned long msglen, + unsigned char *out, unsigned long *outlen); + +int pmac_memory_multi(int cipher, + const unsigned char *key, unsigned long keylen, + unsigned char *out, unsigned long *outlen, + const unsigned char *in, unsigned long inlen, ...); + +int pmac_file(int cipher, + const unsigned char *key, unsigned long keylen, + const char *filename, + unsigned char *out, unsigned long *outlen); + +int pmac_test(void); + +/* internal functions */ +int pmac_ntz(unsigned long x); +void pmac_shift_xor(pmac_state *pmac); + +#endif /* PMAC */ + +#ifdef EAX_MODE + +#if !(defined(LTC_OMAC) && defined(LTC_CTR_MODE)) + #error EAX_MODE requires OMAC and CTR +#endif + +typedef struct { + unsigned char N[MAXBLOCKSIZE]; + symmetric_CTR ctr; + omac_state headeromac, ctomac; +} eax_state; + +int eax_init(eax_state *eax, int cipher, const unsigned char *key, unsigned long keylen, + const unsigned char *nonce, unsigned long noncelen, + const unsigned char *header, unsigned long headerlen); + +int eax_encrypt(eax_state *eax, const unsigned char *pt, unsigned char *ct, unsigned long length); +int eax_decrypt(eax_state *eax, const unsigned char *ct, unsigned char *pt, unsigned long length); +int eax_addheader(eax_state *eax, const unsigned char *header, unsigned long length); +int eax_done(eax_state *eax, unsigned char *tag, unsigned long *taglen); + +int eax_encrypt_authenticate_memory(int cipher, + const unsigned char *key, unsigned long keylen, + const unsigned char *nonce, unsigned long noncelen, + const unsigned char *header, unsigned long headerlen, + const unsigned char *pt, unsigned long ptlen, + unsigned char *ct, + unsigned char *tag, unsigned long *taglen); + +int eax_decrypt_verify_memory(int cipher, + const unsigned char *key, unsigned long keylen, + const unsigned char *nonce, unsigned long noncelen, + const unsigned char *header, unsigned long headerlen, + const unsigned char *ct, unsigned long ctlen, + unsigned char *pt, + unsigned char *tag, unsigned long taglen, + int *stat); + + int eax_test(void); +#endif /* EAX MODE */ + +#ifdef OCB_MODE +typedef struct { + unsigned char L[MAXBLOCKSIZE], /* L value */ + Ls[32][MAXBLOCKSIZE], /* L shifted by i bits to the left */ + Li[MAXBLOCKSIZE], /* value of Li [current value, we calc from previous recall] */ + Lr[MAXBLOCKSIZE], /* L * x^-1 */ + R[MAXBLOCKSIZE], /* R value */ + checksum[MAXBLOCKSIZE]; /* current checksum */ + + symmetric_key key; /* scheduled key for cipher */ + unsigned long block_index; /* index # for current block */ + int cipher, /* cipher idx */ + block_len; /* length of block */ +} ocb_state; + +int ocb_init(ocb_state *ocb, int cipher, + const unsigned char *key, unsigned long keylen, const unsigned char *nonce); + +int ocb_encrypt(ocb_state *ocb, const unsigned char *pt, unsigned char *ct); +int ocb_decrypt(ocb_state *ocb, const unsigned char *ct, unsigned char *pt); + +int ocb_done_encrypt(ocb_state *ocb, + const unsigned char *pt, unsigned long ptlen, + unsigned char *ct, + unsigned char *tag, unsigned long *taglen); + +int ocb_done_decrypt(ocb_state *ocb, + const unsigned char *ct, unsigned long ctlen, + unsigned char *pt, + const unsigned char *tag, unsigned long taglen, int *stat); + +int ocb_encrypt_authenticate_memory(int cipher, + const unsigned char *key, unsigned long keylen, + const unsigned char *nonce, + const unsigned char *pt, unsigned long ptlen, + unsigned char *ct, + unsigned char *tag, unsigned long *taglen); + +int ocb_decrypt_verify_memory(int cipher, + const unsigned char *key, unsigned long keylen, + const unsigned char *nonce, + const unsigned char *ct, unsigned long ctlen, + unsigned char *pt, + const unsigned char *tag, unsigned long taglen, + int *stat); + +int ocb_test(void); + +/* internal functions */ +void ocb_shift_xor(ocb_state *ocb, unsigned char *Z); +int ocb_ntz(unsigned long x); +int s_ocb_done(ocb_state *ocb, const unsigned char *pt, unsigned long ptlen, + unsigned char *ct, unsigned char *tag, unsigned long *taglen, int mode); + +#endif /* OCB_MODE */ + +#ifdef CCM_MODE + +#define CCM_ENCRYPT 0 +#define CCM_DECRYPT 1 + +int ccm_memory(int cipher, + const unsigned char *key, unsigned long keylen, + symmetric_key *uskey, + const unsigned char *nonce, unsigned long noncelen, + const unsigned char *header, unsigned long headerlen, + unsigned char *pt, unsigned long ptlen, + unsigned char *ct, + unsigned char *tag, unsigned long *taglen, + int direction); + +int ccm_test(void); + +#endif /* CCM_MODE */ + +#if defined(LRW_MODE) || defined(GCM_MODE) +void gcm_gf_mult(const unsigned char *a, const unsigned char *b, unsigned char *c); +#endif + + +/* table shared between GCM and LRW */ +#if defined(GCM_TABLES) || defined(LRW_TABLES) || ((defined(GCM_MODE) || defined(GCM_MODE)) && defined(LTC_FAST)) +extern const unsigned char gcm_shift_table[]; +#endif + +#ifdef GCM_MODE + +#define GCM_ENCRYPT 0 +#define GCM_DECRYPT 1 + +#define GCM_MODE_IV 0 +#define GCM_MODE_AAD 1 +#define GCM_MODE_TEXT 2 + +typedef struct { + symmetric_key K; + unsigned char H[16], /* multiplier */ + X[16], /* accumulator */ + Y[16], /* counter */ + Y_0[16], /* initial counter */ + buf[16]; /* buffer for stuff */ + + int cipher, /* which cipher */ + ivmode, /* Which mode is the IV in? */ + mode, /* mode the GCM code is in */ + buflen; /* length of data in buf */ + + ulong64 totlen, /* 64-bit counter used for IV and AAD */ + pttotlen; /* 64-bit counter for the PT */ + +#ifdef GCM_TABLES + unsigned char PC[16][256][16] /* 16 tables of 8x128 */ +#ifdef GCM_TABLES_SSE2 +__attribute__ ((aligned (16))) +#endif +; +#endif +} gcm_state; + +void gcm_mult_h(gcm_state *gcm, unsigned char *I); + +int gcm_init(gcm_state *gcm, int cipher, + const unsigned char *key, int keylen); + +int gcm_reset(gcm_state *gcm); + +int gcm_add_iv(gcm_state *gcm, + const unsigned char *IV, unsigned long IVlen); + +int gcm_add_aad(gcm_state *gcm, + const unsigned char *adata, unsigned long adatalen); + +int gcm_process(gcm_state *gcm, + unsigned char *pt, unsigned long ptlen, + unsigned char *ct, + int direction); + +int gcm_done(gcm_state *gcm, + unsigned char *tag, unsigned long *taglen); + +int gcm_memory( int cipher, + const unsigned char *key, unsigned long keylen, + const unsigned char *IV, unsigned long IVlen, + const unsigned char *adata, unsigned long adatalen, + unsigned char *pt, unsigned long ptlen, + unsigned char *ct, + unsigned char *tag, unsigned long *taglen, + int direction); +int gcm_test(void); + +#endif /* GCM_MODE */ + +#ifdef PELICAN + +typedef struct pelican_state +{ + symmetric_key K; + unsigned char state[16]; + int buflen; +} pelican_state; + +int pelican_init(pelican_state *pelmac, const unsigned char *key, unsigned long keylen); +int pelican_process(pelican_state *pelmac, const unsigned char *in, unsigned long inlen); +int pelican_done(pelican_state *pelmac, unsigned char *out); +int pelican_test(void); + +int pelican_memory(const unsigned char *key, unsigned long keylen, + const unsigned char *in, unsigned long inlen, + unsigned char *out); + +#endif + +#ifdef LTC_XCBC + +typedef struct { + unsigned char K[3][MAXBLOCKSIZE], + IV[MAXBLOCKSIZE]; + + symmetric_key key; + + int cipher, + buflen, + blocksize; +} xcbc_state; + +int xcbc_init(xcbc_state *xcbc, int cipher, const unsigned char *key, unsigned long keylen); +int xcbc_process(xcbc_state *xcbc, const unsigned char *in, unsigned long inlen); +int xcbc_done(xcbc_state *xcbc, unsigned char *out, unsigned long *outlen); +int xcbc_memory(int cipher, + const unsigned char *key, unsigned long keylen, + const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen); +int xcbc_memory_multi(int cipher, + const unsigned char *key, unsigned long keylen, + unsigned char *out, unsigned long *outlen, + const unsigned char *in, unsigned long inlen, ...); +int xcbc_file(int cipher, + const unsigned char *key, unsigned long keylen, + const char *filename, + unsigned char *out, unsigned long *outlen); +int xcbc_test(void); + +#endif + +#ifdef LTC_F9_MODE + +typedef struct { + unsigned char akey[MAXBLOCKSIZE], + ACC[MAXBLOCKSIZE], + IV[MAXBLOCKSIZE]; + + symmetric_key key; + + int cipher, + buflen, + keylen, + blocksize; +} f9_state; + +int f9_init(f9_state *f9, int cipher, const unsigned char *key, unsigned long keylen); +int f9_process(f9_state *f9, const unsigned char *in, unsigned long inlen); +int f9_done(f9_state *f9, unsigned char *out, unsigned long *outlen); +int f9_memory(int cipher, + const unsigned char *key, unsigned long keylen, + const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen); +int f9_memory_multi(int cipher, + const unsigned char *key, unsigned long keylen, + unsigned char *out, unsigned long *outlen, + const unsigned char *in, unsigned long inlen, ...); +int f9_file(int cipher, + const unsigned char *key, unsigned long keylen, + const char *filename, + unsigned char *out, unsigned long *outlen); +int f9_test(void); + +#endif + + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/plugins/pro1_data_zip/ltc/headers/tomcrypt_macros.h b/src/plugins/pro1_data_zip/ltc/headers/tomcrypt_macros.h new file mode 100644 index 0000000..6e4d757 --- /dev/null +++ b/src/plugins/pro1_data_zip/ltc/headers/tomcrypt_macros.h @@ -0,0 +1,424 @@ +/* fix for MSVC ...evil! */ +#ifdef _MSC_VER + #define CONST64(n) n ## ui64 + typedef unsigned __int64 ulong64; +#else + #define CONST64(n) n ## ULL + typedef unsigned long long ulong64; +#endif + +/* this is the "32-bit at least" data type + * Re-define it to suit your platform but it must be at least 32-bits + */ +#if defined(__x86_64__) || (defined(__sparc__) && defined(__arch64__)) + typedef unsigned ulong32; +#else + typedef unsigned long ulong32; +#endif + +/* ---- HELPER MACROS ---- */ +#ifdef ENDIAN_NEUTRAL + +#define STORE32L(x, y) \ + { (y)[3] = (unsigned char)(((x)>>24)&255); (y)[2] = (unsigned char)(((x)>>16)&255); \ + (y)[1] = (unsigned char)(((x)>>8)&255); (y)[0] = (unsigned char)((x)&255); } + +#define LOAD32L(x, y) \ + { x = ((unsigned long)((y)[3] & 255)<<24) | \ + ((unsigned long)((y)[2] & 255)<<16) | \ + ((unsigned long)((y)[1] & 255)<<8) | \ + ((unsigned long)((y)[0] & 255)); } + +#define STORE64L(x, y) \ + { (y)[7] = (unsigned char)(((x)>>56)&255); (y)[6] = (unsigned char)(((x)>>48)&255); \ + (y)[5] = (unsigned char)(((x)>>40)&255); (y)[4] = (unsigned char)(((x)>>32)&255); \ + (y)[3] = (unsigned char)(((x)>>24)&255); (y)[2] = (unsigned char)(((x)>>16)&255); \ + (y)[1] = (unsigned char)(((x)>>8)&255); (y)[0] = (unsigned char)((x)&255); } + +#define LOAD64L(x, y) \ + { x = (((ulong64)((y)[7] & 255))<<56)|(((ulong64)((y)[6] & 255))<<48)| \ + (((ulong64)((y)[5] & 255))<<40)|(((ulong64)((y)[4] & 255))<<32)| \ + (((ulong64)((y)[3] & 255))<<24)|(((ulong64)((y)[2] & 255))<<16)| \ + (((ulong64)((y)[1] & 255))<<8)|(((ulong64)((y)[0] & 255))); } + +#define STORE32H(x, y) \ + { (y)[0] = (unsigned char)(((x)>>24)&255); (y)[1] = (unsigned char)(((x)>>16)&255); \ + (y)[2] = (unsigned char)(((x)>>8)&255); (y)[3] = (unsigned char)((x)&255); } + +#define LOAD32H(x, y) \ + { x = ((unsigned long)((y)[0] & 255)<<24) | \ + ((unsigned long)((y)[1] & 255)<<16) | \ + ((unsigned long)((y)[2] & 255)<<8) | \ + ((unsigned long)((y)[3] & 255)); } + +#define STORE64H(x, y) \ + { (y)[0] = (unsigned char)(((x)>>56)&255); (y)[1] = (unsigned char)(((x)>>48)&255); \ + (y)[2] = (unsigned char)(((x)>>40)&255); (y)[3] = (unsigned char)(((x)>>32)&255); \ + (y)[4] = (unsigned char)(((x)>>24)&255); (y)[5] = (unsigned char)(((x)>>16)&255); \ + (y)[6] = (unsigned char)(((x)>>8)&255); (y)[7] = (unsigned char)((x)&255); } + +#define LOAD64H(x, y) \ + { x = (((ulong64)((y)[0] & 255))<<56)|(((ulong64)((y)[1] & 255))<<48) | \ + (((ulong64)((y)[2] & 255))<<40)|(((ulong64)((y)[3] & 255))<<32) | \ + (((ulong64)((y)[4] & 255))<<24)|(((ulong64)((y)[5] & 255))<<16) | \ + (((ulong64)((y)[6] & 255))<<8)|(((ulong64)((y)[7] & 255))); } + +#endif /* ENDIAN_NEUTRAL */ + +#ifdef ENDIAN_LITTLE + +#if !defined(LTC_NO_BSWAP) && (defined(INTEL_CC) || (defined(__GNUC__) && (defined(__DJGPP__) || defined(__CYGWIN__) || defined(__MINGW32__) || defined(__i386__) || defined(__x86_64__)))) + +#define STORE32H(x, y) \ +asm __volatile__ ( \ + "bswapl %0 \n\t" \ + "movl %0,(%1)\n\t" \ + "bswapl %0 \n\t" \ + ::"r"(x), "r"(y)); + +#define LOAD32H(x, y) \ +asm __volatile__ ( \ + "movl (%1),%0\n\t" \ + "bswapl %0\n\t" \ + :"=r"(x): "r"(y)); + +#else + +#define STORE32H(x, y) \ + { (y)[0] = (unsigned char)(((x)>>24)&255); (y)[1] = (unsigned char)(((x)>>16)&255); \ + (y)[2] = (unsigned char)(((x)>>8)&255); (y)[3] = (unsigned char)((x)&255); } + +#define LOAD32H(x, y) \ + { x = ((unsigned long)((y)[0] & 255)<<24) | \ + ((unsigned long)((y)[1] & 255)<<16) | \ + ((unsigned long)((y)[2] & 255)<<8) | \ + ((unsigned long)((y)[3] & 255)); } + +#endif + + +/* x86_64 processor */ +#if !defined(LTC_NO_BSWAP) && (defined(__GNUC__) && defined(__x86_64__)) + +#define STORE64H(x, y) \ +asm __volatile__ ( \ + "bswapq %0 \n\t" \ + "movq %0,(%1)\n\t" \ + "bswapq %0 \n\t" \ + ::"r"(x), "r"(y)); + +#define LOAD64H(x, y) \ +asm __volatile__ ( \ + "movq (%1),%0\n\t" \ + "bswapq %0\n\t" \ + :"=r"(x): "r"(y)); + +#else + +#define STORE64H(x, y) \ + { (y)[0] = (unsigned char)(((x)>>56)&255); (y)[1] = (unsigned char)(((x)>>48)&255); \ + (y)[2] = (unsigned char)(((x)>>40)&255); (y)[3] = (unsigned char)(((x)>>32)&255); \ + (y)[4] = (unsigned char)(((x)>>24)&255); (y)[5] = (unsigned char)(((x)>>16)&255); \ + (y)[6] = (unsigned char)(((x)>>8)&255); (y)[7] = (unsigned char)((x)&255); } + +#define LOAD64H(x, y) \ + { x = (((ulong64)((y)[0] & 255))<<56)|(((ulong64)((y)[1] & 255))<<48) | \ + (((ulong64)((y)[2] & 255))<<40)|(((ulong64)((y)[3] & 255))<<32) | \ + (((ulong64)((y)[4] & 255))<<24)|(((ulong64)((y)[5] & 255))<<16) | \ + (((ulong64)((y)[6] & 255))<<8)|(((ulong64)((y)[7] & 255))); } + +#endif + +#ifdef ENDIAN_32BITWORD + +#define STORE32L(x, y) \ + { ulong32 __t = (x); XMEMCPY(y, &__t, 4); } + +#define LOAD32L(x, y) \ + XMEMCPY(&(x), y, 4); + +#define STORE64L(x, y) \ + { (y)[7] = (unsigned char)(((x)>>56)&255); (y)[6] = (unsigned char)(((x)>>48)&255); \ + (y)[5] = (unsigned char)(((x)>>40)&255); (y)[4] = (unsigned char)(((x)>>32)&255); \ + (y)[3] = (unsigned char)(((x)>>24)&255); (y)[2] = (unsigned char)(((x)>>16)&255); \ + (y)[1] = (unsigned char)(((x)>>8)&255); (y)[0] = (unsigned char)((x)&255); } + +#define LOAD64L(x, y) \ + { x = (((ulong64)((y)[7] & 255))<<56)|(((ulong64)((y)[6] & 255))<<48)| \ + (((ulong64)((y)[5] & 255))<<40)|(((ulong64)((y)[4] & 255))<<32)| \ + (((ulong64)((y)[3] & 255))<<24)|(((ulong64)((y)[2] & 255))<<16)| \ + (((ulong64)((y)[1] & 255))<<8)|(((ulong64)((y)[0] & 255))); } + +#else /* 64-bit words then */ + +#define STORE32L(x, y) \ + { ulong32 __t = (x); XMEMCPY(y, &__t, 4); } + +#define LOAD32L(x, y) \ + { XMEMCPY(&(x), y, 4); x &= 0xFFFFFFFF; } + +#define STORE64L(x, y) \ + { ulong64 __t = (x); XMEMCPY(y, &__t, 8); } + +#define LOAD64L(x, y) \ + { XMEMCPY(&(x), y, 8); } + +#endif /* ENDIAN_64BITWORD */ + +#endif /* ENDIAN_LITTLE */ + +#ifdef ENDIAN_BIG +#define STORE32L(x, y) \ + { (y)[3] = (unsigned char)(((x)>>24)&255); (y)[2] = (unsigned char)(((x)>>16)&255); \ + (y)[1] = (unsigned char)(((x)>>8)&255); (y)[0] = (unsigned char)((x)&255); } + +#define LOAD32L(x, y) \ + { x = ((unsigned long)((y)[3] & 255)<<24) | \ + ((unsigned long)((y)[2] & 255)<<16) | \ + ((unsigned long)((y)[1] & 255)<<8) | \ + ((unsigned long)((y)[0] & 255)); } + +#define STORE64L(x, y) \ + { (y)[7] = (unsigned char)(((x)>>56)&255); (y)[6] = (unsigned char)(((x)>>48)&255); \ + (y)[5] = (unsigned char)(((x)>>40)&255); (y)[4] = (unsigned char)(((x)>>32)&255); \ + (y)[3] = (unsigned char)(((x)>>24)&255); (y)[2] = (unsigned char)(((x)>>16)&255); \ + (y)[1] = (unsigned char)(((x)>>8)&255); (y)[0] = (unsigned char)((x)&255); } + +#define LOAD64L(x, y) \ + { x = (((ulong64)((y)[7] & 255))<<56)|(((ulong64)((y)[6] & 255))<<48) | \ + (((ulong64)((y)[5] & 255))<<40)|(((ulong64)((y)[4] & 255))<<32) | \ + (((ulong64)((y)[3] & 255))<<24)|(((ulong64)((y)[2] & 255))<<16) | \ + (((ulong64)((y)[1] & 255))<<8)|(((ulong64)((y)[0] & 255))); } + +#ifdef ENDIAN_32BITWORD + +#define STORE32H(x, y) \ + { ulong32 __t = (x); XMEMCPY(y, &__t, 4); } + +#define LOAD32H(x, y) \ + XMEMCPY(&(x), y, 4); + +#define STORE64H(x, y) \ + { (y)[0] = (unsigned char)(((x)>>56)&255); (y)[1] = (unsigned char)(((x)>>48)&255); \ + (y)[2] = (unsigned char)(((x)>>40)&255); (y)[3] = (unsigned char)(((x)>>32)&255); \ + (y)[4] = (unsigned char)(((x)>>24)&255); (y)[5] = (unsigned char)(((x)>>16)&255); \ + (y)[6] = (unsigned char)(((x)>>8)&255); (y)[7] = (unsigned char)((x)&255); } + +#define LOAD64H(x, y) \ + { x = (((ulong64)((y)[0] & 255))<<56)|(((ulong64)((y)[1] & 255))<<48)| \ + (((ulong64)((y)[2] & 255))<<40)|(((ulong64)((y)[3] & 255))<<32)| \ + (((ulong64)((y)[4] & 255))<<24)|(((ulong64)((y)[5] & 255))<<16)| \ + (((ulong64)((y)[6] & 255))<<8)| (((ulong64)((y)[7] & 255))); } + +#else /* 64-bit words then */ + +#define STORE32H(x, y) \ + { ulong32 __t = (x); XMEMCPY(y, &__t, 4); } + +#define LOAD32H(x, y) \ + { XMEMCPY(&(x), y, 4); x &= 0xFFFFFFFF; } + +#define STORE64H(x, y) \ + { ulong64 __t = (x); XMEMCPY(y, &__t, 8); } + +#define LOAD64H(x, y) \ + { XMEMCPY(&(x), y, 8); } + +#endif /* ENDIAN_64BITWORD */ +#endif /* ENDIAN_BIG */ + +#define BSWAP(x) ( ((x>>24)&0x000000FFUL) | ((x<<24)&0xFF000000UL) | \ + ((x>>8)&0x0000FF00UL) | ((x<<8)&0x00FF0000UL) ) + + +/* 32-bit Rotates */ +#if defined(_MSC_VER) + +/* instrinsic rotate */ +#include +#pragma intrinsic(_lrotr,_lrotl) +#define ROR(x,n) _lrotr(x,n) +#define ROL(x,n) _lrotl(x,n) +#define RORc(x,n) _lrotr(x,n) +#define ROLc(x,n) _lrotl(x,n) + +#elif !defined(__STRICT_ANSI__) && defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) && !defined(INTEL_CC) && !defined(LTC_NO_ASM) + +static inline unsigned ROL(unsigned word, int i) +{ + asm ("roll %%cl,%0" + :"=r" (word) + :"0" (word),"c" (i)); + return word; +} + +static inline unsigned ROR(unsigned word, int i) +{ + asm ("rorl %%cl,%0" + :"=r" (word) + :"0" (word),"c" (i)); + return word; +} + +#ifndef LTC_NO_ROLC + +static inline unsigned ROLc(unsigned word, const int i) +{ + asm ("roll %2,%0" + :"=r" (word) + :"0" (word),"I" (i)); + return word; +} + +static inline unsigned RORc(unsigned word, const int i) +{ + asm ("rorl %2,%0" + :"=r" (word) + :"0" (word),"I" (i)); + return word; +} + +#else + +#define ROLc ROL +#define RORc ROR + +#endif + +#elif !defined(__STRICT_ANSI__) && defined(LTC_PPC32) + +static inline unsigned ROL(unsigned word, int i) +{ + asm ("rotlw %0,%0,%2" + :"=r" (word) + :"0" (word),"r" (i)); + return word; +} + +static inline unsigned ROR(unsigned word, int i) +{ + asm ("rotlw %0,%0,%2" + :"=r" (word) + :"0" (word),"r" (32-i)); + return word; +} + +#ifndef LTC_NO_ROLC + +static inline unsigned ROLc(unsigned word, const int i) +{ + asm ("rotlwi %0,%0,%2" + :"=r" (word) + :"0" (word),"I" (i)); + return word; +} + +static inline unsigned RORc(unsigned word, const int i) +{ + asm ("rotrwi %0,%0,%2" + :"=r" (word) + :"0" (word),"I" (i)); + return word; +} + +#else + +#define ROLc ROL +#define RORc ROR + +#endif + + +#else + +/* rotates the hard way */ +#define ROL(x, y) ( (((unsigned long)(x)<<(unsigned long)((y)&31)) | (((unsigned long)(x)&0xFFFFFFFFUL)>>(unsigned long)(32-((y)&31)))) & 0xFFFFFFFFUL) +#define ROR(x, y) ( ((((unsigned long)(x)&0xFFFFFFFFUL)>>(unsigned long)((y)&31)) | ((unsigned long)(x)<<(unsigned long)(32-((y)&31)))) & 0xFFFFFFFFUL) +#define ROLc(x, y) ( (((unsigned long)(x)<<(unsigned long)((y)&31)) | (((unsigned long)(x)&0xFFFFFFFFUL)>>(unsigned long)(32-((y)&31)))) & 0xFFFFFFFFUL) +#define RORc(x, y) ( ((((unsigned long)(x)&0xFFFFFFFFUL)>>(unsigned long)((y)&31)) | ((unsigned long)(x)<<(unsigned long)(32-((y)&31)))) & 0xFFFFFFFFUL) + +#endif + + +/* 64-bit Rotates */ +#if !defined(__STRICT_ANSI__) && defined(__GNUC__) && defined(__x86_64__) && !defined(LTC_NO_ASM) + +static inline unsigned long ROL64(unsigned long word, int i) +{ + asm("rolq %%cl,%0" + :"=r" (word) + :"0" (word),"c" (i)); + return word; +} + +static inline unsigned long ROR64(unsigned long word, int i) +{ + asm("rorq %%cl,%0" + :"=r" (word) + :"0" (word),"c" (i)); + return word; +} + +#ifndef LTC_NO_ROLC + +static inline unsigned long ROL64c(unsigned long word, const int i) +{ + asm("rolq %2,%0" + :"=r" (word) + :"0" (word),"J" (i)); + return word; +} + +static inline unsigned long ROR64c(unsigned long word, const int i) +{ + asm("rorq %2,%0" + :"=r" (word) + :"0" (word),"J" (i)); + return word; +} + +#else /* LTC_NO_ROLC */ + +#define ROL64c ROL64 +#define ROR64c ROR64 + +#endif + +#else /* Not x86_64 */ + +#define ROL64(x, y) \ + ( (((x)<<((ulong64)(y)&63)) | \ + (((x)&CONST64(0xFFFFFFFFFFFFFFFF))>>((ulong64)64-((y)&63)))) & CONST64(0xFFFFFFFFFFFFFFFF)) + +#define ROR64(x, y) \ + ( ((((x)&CONST64(0xFFFFFFFFFFFFFFFF))>>((ulong64)(y)&CONST64(63))) | \ + ((x)<<((ulong64)(64-((y)&CONST64(63)))))) & CONST64(0xFFFFFFFFFFFFFFFF)) + +#define ROL64c(x, y) \ + ( (((x)<<((ulong64)(y)&63)) | \ + (((x)&CONST64(0xFFFFFFFFFFFFFFFF))>>((ulong64)64-((y)&63)))) & CONST64(0xFFFFFFFFFFFFFFFF)) + +#define ROR64c(x, y) \ + ( ((((x)&CONST64(0xFFFFFFFFFFFFFFFF))>>((ulong64)(y)&CONST64(63))) | \ + ((x)<<((ulong64)(64-((y)&CONST64(63)))))) & CONST64(0xFFFFFFFFFFFFFFFF)) + +#endif + +#ifndef MAX + #define MAX(x, y) ( ((x)>(y))?(x):(y) ) +#endif + +#ifndef MIN + #define MIN(x, y) ( ((x)<(y))?(x):(y) ) +#endif + +/* extract a byte portably */ +#ifdef _MSC_VER + #define byte(x, n) ((unsigned char)((x) >> (8 * (n)))) +#else + #define byte(x, n) (((x) >> (8 * (n))) & 255) +#endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/plugins/pro1_data_zip/ltc/headers/tomcrypt_math.h b/src/plugins/pro1_data_zip/ltc/headers/tomcrypt_math.h new file mode 100644 index 0000000..e6ee799 --- /dev/null +++ b/src/plugins/pro1_data_zip/ltc/headers/tomcrypt_math.h @@ -0,0 +1,500 @@ +/** math functions **/ + +#define LTC_MP_LT -1 +#define LTC_MP_EQ 0 +#define LTC_MP_GT 1 + +#define LTC_MP_NO 0 +#define LTC_MP_YES 1 + +#ifndef MECC + typedef void ecc_point; +#endif + +#ifndef MRSA + typedef void rsa_key; +#endif + +/** math descriptor */ +typedef struct { + /** Name of the math provider */ + char *name; + + /** Bits per digit, amount of bits must fit in an unsigned long */ + int bits_per_digit; + +/* ---- init/deinit functions ---- */ + + /** initialize a bignum + @param a The number to initialize + @return CRYPT_OK on success + */ + int (*init)(void **a); + + /** init copy + @param dst The number to initialize and write to + @param src The number to copy from + @return CRYPT_OK on success + */ + int (*init_copy)(void **dst, void *src); + + /** deinit + @param a The number to free + @return CRYPT_OK on success + */ + void (*deinit)(void *a); + +/* ---- data movement ---- */ + + /** negate + @param src The number to negate + @param dst The destination + @return CRYPT_OK on success + */ + int (*neg)(void *src, void *dst); + + /** copy + @param src The number to copy from + @param dst The number to write to + @return CRYPT_OK on success + */ + int (*copy)(void *src, void *dst); + +/* ---- trivial low level functions ---- */ + + /** set small constant + @param a Number to write to + @param n Source upto bits_per_digit (actually meant for very small constants) + @return CRYPT_OK on succcess + */ + int (*set_int)(void *a, unsigned long n); + + /** get small constant + @param a Number to read, only fetches upto bits_per_digit from the number + @return The lower bits_per_digit of the integer (unsigned) + */ + unsigned long (*get_int)(void *a); + + /** get digit n + @param a The number to read from + @param n The number of the digit to fetch + @return The bits_per_digit sized n'th digit of a + */ + unsigned long (*get_digit)(void *a, int n); + + /** Get the number of digits that represent the number + @param a The number to count + @return The number of digits used to represent the number + */ + int (*get_digit_count)(void *a); + + /** compare two integers + @param a The left side integer + @param b The right side integer + @return LTC_MP_LT if a < b, LTC_MP_GT if a > b and LTC_MP_EQ otherwise. (signed comparison) + */ + int (*compare)(void *a, void *b); + + /** compare against int + @param a The left side integer + @param b The right side integer (upto bits_per_digit) + @return LTC_MP_LT if a < b, LTC_MP_GT if a > b and LTC_MP_EQ otherwise. (signed comparison) + */ + int (*compare_d)(void *a, unsigned long n); + + /** Count the number of bits used to represent the integer + @param a The integer to count + @return The number of bits required to represent the integer + */ + int (*count_bits)(void * a); + + /** Count the number of LSB bits which are zero + @param a The integer to count + @return The number of contiguous zero LSB bits + */ + int (*count_lsb_bits)(void *a); + + /** Compute a power of two + @param a The integer to store the power in + @param n The power of two you want to store (a = 2^n) + @return CRYPT_OK on success + */ + int (*twoexpt)(void *a , int n); + +/* ---- radix conversions ---- */ + + /** read ascii string + @param a The integer to store into + @param str The string to read + @param radix The radix the integer has been represented in (2-64) + @return CRYPT_OK on success + */ + int (*read_radix)(void *a, const char *str, int radix); + + /** write number to string + @param a The integer to store + @param str The destination for the string + @param radix The radix the integer is to be represented in (2-64) + @return CRYPT_OK on success + */ + int (*write_radix)(void *a, char *str, int radix); + + /** get size as unsigned char string + @param a The integer to get the size (when stored in array of octets) + @return The length of the integer + */ + unsigned long (*unsigned_size)(void *a); + + /** store an integer as an array of octets + @param src The integer to store + @param dst The buffer to store the integer in + @return CRYPT_OK on success + */ + int (*unsigned_write)(void *src, unsigned char *dst); + + /** read an array of octets and store as integer + @param dst The integer to load + @param src The array of octets + @param len The number of octets + @return CRYPT_OK on success + */ + int (*unsigned_read)(void *dst, unsigned char *src, unsigned long len); + +/* ---- basic math ---- */ + + /** add two integers + @param a The first source integer + @param b The second source integer + @param c The destination of "a + b" + @return CRYPT_OK on success + */ + int (*add)(void *a, void *b, void *c); + + + /** add two integers + @param a The first source integer + @param b The second source integer (single digit of upto bits_per_digit in length) + @param c The destination of "a + b" + @return CRYPT_OK on success + */ + int (*addi)(void *a, unsigned long b, void *c); + + /** subtract two integers + @param a The first source integer + @param b The second source integer + @param c The destination of "a - b" + @return CRYPT_OK on success + */ + int (*sub)(void *a, void *b, void *c); + + /** subtract two integers + @param a The first source integer + @param b The second source integer (single digit of upto bits_per_digit in length) + @param c The destination of "a - b" + @return CRYPT_OK on success + */ + int (*subi)(void *a, unsigned long b, void *c); + + /** multiply two integers + @param a The first source integer + @param b The second source integer (single digit of upto bits_per_digit in length) + @param c The destination of "a * b" + @return CRYPT_OK on success + */ + int (*mul)(void *a, void *b, void *c); + + /** multiply two integers + @param a The first source integer + @param b The second source integer (single digit of upto bits_per_digit in length) + @param c The destination of "a * b" + @return CRYPT_OK on success + */ + int (*muli)(void *a, unsigned long b, void *c); + + /** Square an integer + @param a The integer to square + @param b The destination + @return CRYPT_OK on success + */ + int (*sqr)(void *a, void *b); + + /** Divide an integer + @param a The dividend + @param b The divisor + @param c The quotient (can be NULL to signify don't care) + @param d The remainder (can be NULL to signify don't care) + @return CRYPT_OK on success + */ + int (*mpdiv)(void *a, void *b, void *c, void *d); + + /** divide by two + @param a The integer to divide (shift right) + @param b The destination + @return CRYPT_OK on success + */ + int (*div_2)(void *a, void *b); + + /** Get remainder (small value) + @param a The integer to reduce + @param b The modulus (upto bits_per_digit in length) + @param c The destination for the residue + @return CRYPT_OK on success + */ + int (*modi)(void *a, unsigned long b, unsigned long *c); + + /** gcd + @param a The first integer + @param b The second integer + @param c The destination for (a, b) + @return CRYPT_OK on success + */ + int (*gcd)(void *a, void *b, void *c); + + /** lcm + @param a The first integer + @param b The second integer + @param c The destination for [a, b] + @return CRYPT_OK on success + */ + int (*lcm)(void *a, void *b, void *c); + + /** Modular multiplication + @param a The first source + @param b The second source + @param c The modulus + @param d The destination (a*b mod c) + @return CRYPT_OK on success + */ + int (*mulmod)(void *a, void *b, void *c, void *d); + + /** Modular squaring + @param a The first source + @param b The modulus + @param c The destination (a*a mod b) + @return CRYPT_OK on success + */ + int (*sqrmod)(void *a, void *b, void *c); + + /** Modular inversion + @param a The value to invert + @param b The modulus + @param c The destination (1/a mod b) + @return CRYPT_OK on success + */ + int (*invmod)(void *, void *, void *); + +/* ---- reduction ---- */ + + /** setup montgomery + @param a The modulus + @param b The destination for the reduction digit + @return CRYPT_OK on success + */ + int (*montgomery_setup)(void *a, void **b); + + /** get normalization value + @param a The destination for the normalization value + @param b The modulus + @return CRYPT_OK on success + */ + int (*montgomery_normalization)(void *a, void *b); + + /** reduce a number + @param a The number [and dest] to reduce + @param b The modulus + @param c The value "b" from montgomery_setup() + @return CRYPT_OK on success + */ + int (*montgomery_reduce)(void *a, void *b, void *c); + + /** clean up (frees memory) + @param a The value "b" from montgomery_setup() + @return CRYPT_OK on success + */ + void (*montgomery_deinit)(void *a); + +/* ---- exponentiation ---- */ + + /** Modular exponentiation + @param a The base integer + @param b The power (can be negative) integer + @param c The modulus integer + @param d The destination + @return CRYPT_OK on success + */ + int (*exptmod)(void *a, void *b, void *c, void *d); + + /** Primality testing + @param a The integer to test + @param b The destination of the result (FP_YES if prime) + @return CRYPT_OK on success + */ + int (*isprime)(void *a, int *b); + +/* ---- (optional) ecc point math ---- */ + + /** ECC GF(p) point multiplication (from the NIST curves) + @param k The integer to multiply the point by + @param G The point to multiply + @param R The destination for kG + @param modulus The modulus for the field + @param map Boolean indicated whether to map back to affine or not (can be ignored if you work in affine only) + @return CRYPT_OK on success + */ + int (*ecc_ptmul)(void *k, ecc_point *G, ecc_point *R, void *modulus, int map); + + /** ECC GF(p) point addition + @param P The first point + @param Q The second point + @param R The destination of P + Q + @param modulus The modulus + @param mp The "b" value from montgomery_setup() + @return CRYPT_OK on success + */ + int (*ecc_ptadd)(ecc_point *P, ecc_point *Q, ecc_point *R, void *modulus, void *mp); + + /** ECC GF(p) point double + @param P The first point + @param R The destination of 2P + @param modulus The modulus + @param mp The "b" value from montgomery_setup() + @return CRYPT_OK on success + */ + int (*ecc_ptdbl)(ecc_point *P, ecc_point *R, void *modulus, void *mp); + + /** ECC mapping from projective to affine, currently uses (x,y,z) => (x/z^2, y/z^3, 1) + @param P The point to map + @param modulus The modulus + @param mp The "b" value from montgomery_setup() + @return CRYPT_OK on success + @remark The mapping can be different but keep in mind a ecc_point only has three + integers (x,y,z) so if you use a different mapping you have to make it fit. + */ + int (*ecc_map)(ecc_point *P, void *modulus, void *mp); + + /** Computes kA*A + kB*B = C using Shamir's Trick + @param A First point to multiply + @param kA What to multiple A by + @param B Second point to multiply + @param kB What to multiple B by + @param C [out] Destination point (can overlap with A or B + @param modulus Modulus for curve + @return CRYPT_OK on success + */ + int (*ecc_mul2add)(ecc_point *A, void *kA, + ecc_point *B, void *kB, + ecc_point *C, + void *modulus); + +/* ---- (optional) rsa optimized math (for internal CRT) ---- */ + + /** RSA Key Generation + @param prng An active PRNG state + @param wprng The index of the PRNG desired + @param size The size of the modulus (key size) desired (octets) + @param e The "e" value (public key). e==65537 is a good choice + @param key [out] Destination of a newly created private key pair + @return CRYPT_OK if successful, upon error all allocated ram is freed + */ + int (*rsa_keygen)(prng_state *prng, int wprng, int size, long e, rsa_key *key); + + + /** RSA exponentiation + @param in The octet array representing the base + @param inlen The length of the input + @param out The destination (to be stored in an octet array format) + @param outlen The length of the output buffer and the resulting size (zero padded to the size of the modulus) + @param which PK_PUBLIC for public RSA and PK_PRIVATE for private RSA + @param key The RSA key to use + @return CRYPT_OK on success + */ + int (*rsa_me)(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen, int which, + rsa_key *key); +} ltc_math_descriptor; + +extern ltc_math_descriptor ltc_mp; + +int ltc_init_multi(void **a, ...); +void ltc_deinit_multi(void *a, ...); + +#ifdef LTM_DESC +extern const ltc_math_descriptor ltm_desc; +#endif + +#ifdef TFM_DESC +extern const ltc_math_descriptor tfm_desc; +#endif + +#ifdef GMP_DESC +extern const ltc_math_descriptor gmp_desc; +#endif + +#if !defined(DESC_DEF_ONLY) && defined(LTC_SOURCE) + +#define MP_DIGIT_BIT ltc_mp.bits_per_digit + +/* some handy macros */ +#define mp_init(a) ltc_mp.init(a) +#define mp_init_multi ltc_init_multi +#define mp_clear(a) ltc_mp.deinit(a) +#define mp_clear_multi ltc_deinit_multi +#define mp_init_copy(a, b) ltc_mp.init_copy(a, b) + +#define mp_neg(a, b) ltc_mp.neg(a, b) +#define mp_copy(a, b) ltc_mp.copy(a, b) + +#define mp_set(a, b) ltc_mp.set_int(a, b) +#define mp_set_int(a, b) ltc_mp.set_int(a, b) +#define mp_get_int(a) ltc_mp.get_int(a) +#define mp_get_digit(a, n) ltc_mp.get_digit(a, n) +#define mp_get_digit_count(a) ltc_mp.get_digit_count(a) +#define mp_cmp(a, b) ltc_mp.compare(a, b) +#define mp_cmp_d(a, b) ltc_mp.compare_d(a, b) +#define mp_count_bits(a) ltc_mp.count_bits(a) +#define mp_cnt_lsb(a) ltc_mp.count_lsb_bits(a) +#define mp_2expt(a, b) ltc_mp.twoexpt(a, b) + +#define mp_read_radix(a, b, c) ltc_mp.read_radix(a, b, c) +#define mp_toradix(a, b, c) ltc_mp.write_radix(a, b, c) +#define mp_unsigned_bin_size(a) ltc_mp.unsigned_size(a) +#define mp_to_unsigned_bin(a, b) ltc_mp.unsigned_write(a, b) +#define mp_read_unsigned_bin(a, b, c) ltc_mp.unsigned_read(a, b, c) + +#define mp_add(a, b, c) ltc_mp.add(a, b, c) +#define mp_add_d(a, b, c) ltc_mp.addi(a, b, c) +#define mp_sub(a, b, c) ltc_mp.sub(a, b, c) +#define mp_sub_d(a, b, c) ltc_mp.subi(a, b, c) +#define mp_mul(a, b, c) ltc_mp.mul(a, b, c) +#define mp_mul_d(a, b, c) ltc_mp.muli(a, b, c) +#define mp_sqr(a, b) ltc_mp.sqr(a, b) +#define mp_div(a, b, c, d) ltc_mp.mpdiv(a, b, c, d) +#define mp_div_2(a, b) ltc_mp.div_2(a, b) +#define mp_mod(a, b, c) ltc_mp.mpdiv(a, b, NULL, c) +#define mp_mod_d(a, b, c) ltc_mp.modi(a, b, c) +#define mp_gcd(a, b, c) ltc_mp.gcd(a, b, c) +#define mp_lcm(a, b, c) ltc_mp.lcm(a, b, c) + +#define mp_mulmod(a, b, c, d) ltc_mp.mulmod(a, b, c, d) +#define mp_sqrmod(a, b, c) ltc_mp.sqrmod(a, b, c) +#define mp_invmod(a, b, c) ltc_mp.invmod(a, b, c) + +#define mp_montgomery_setup(a, b) ltc_mp.montgomery_setup(a, b) +#define mp_montgomery_normalization(a, b) ltc_mp.montgomery_normalization(a, b) +#define mp_montgomery_reduce(a, b, c) ltc_mp.montgomery_reduce(a, b, c) +#define mp_montgomery_free(a) ltc_mp.montgomery_deinit(a) + +#define mp_exptmod(a,b,c,d) ltc_mp.exptmod(a,b,c,d) +#define mp_prime_is_prime(a, b, c) ltc_mp.isprime(a, c) + +#define mp_iszero(a) (mp_cmp_d(a, 0) == LTC_MP_EQ ? LTC_MP_YES : LTC_MP_NO) +#define mp_isodd(a) (mp_get_digit_count(a) > 0 ? (mp_get_digit(a, 0) & 1 ? LTC_MP_YES : LTC_MP_NO) : LTC_MP_NO) +#define mp_exch(a, b) do { void *ABC__tmp = a; a = b; b = ABC__tmp; } while(0); + +#define mp_tohex(a, b) mp_toradix(a, b, 16) + +#endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/plugins/pro1_data_zip/ltc/headers/tomcrypt_misc.h b/src/plugins/pro1_data_zip/ltc/headers/tomcrypt_misc.h new file mode 100644 index 0000000..ec0e655 --- /dev/null +++ b/src/plugins/pro1_data_zip/ltc/headers/tomcrypt_misc.h @@ -0,0 +1,23 @@ +/* ---- BASE64 Routines ---- */ +#ifdef BASE64 +int base64_encode(const unsigned char *in, unsigned long len, + unsigned char *out, unsigned long *outlen); + +int base64_decode(const unsigned char *in, unsigned long len, + unsigned char *out, unsigned long *outlen); +#endif + +/* ---- MEM routines ---- */ +void zeromem(void *dst, size_t len); +void burn_stack(unsigned long len); + +const char *error_to_string(int err); + +extern const char *crypt_build_settings; + +/* ---- HMM ---- */ +int crypt_fsa(void *mp, ...); + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/plugins/pro1_data_zip/ltc/headers/tomcrypt_pk.h b/src/plugins/pro1_data_zip/ltc/headers/tomcrypt_pk.h new file mode 100644 index 0000000..079ae3e --- /dev/null +++ b/src/plugins/pro1_data_zip/ltc/headers/tomcrypt_pk.h @@ -0,0 +1,544 @@ +/* ---- NUMBER THEORY ---- */ + +enum { + PK_PUBLIC=0, + PK_PRIVATE=1 +}; + +int rand_prime(void *N, long len, prng_state *prng, int wprng); + +/* ---- RSA ---- */ +#ifdef MRSA + +/* Min and Max RSA key sizes (in bits) */ +#define MIN_RSA_SIZE 1024 +#define MAX_RSA_SIZE 4096 + +/** RSA PKCS style key */ +typedef struct Rsa_key { + /** Type of key, PK_PRIVATE or PK_PUBLIC */ + int type; + /** The public exponent */ + void *e; + /** The private exponent */ + void *d; + /** The modulus */ + void *N; + /** The p factor of N */ + void *p; + /** The q factor of N */ + void *q; + /** The 1/q mod p CRT param */ + void *qP; + /** The d mod (p - 1) CRT param */ + void *dP; + /** The d mod (q - 1) CRT param */ + void *dQ; +} rsa_key; + +int rsa_make_key(prng_state *prng, int wprng, int size, long e, rsa_key *key); + +int rsa_exptmod(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen, int which, + rsa_key *key); + +void rsa_free(rsa_key *key); + +/* These use PKCS #1 v2.0 padding */ +#define rsa_encrypt_key(_in, _inlen, _out, _outlen, _lparam, _lparamlen, _prng, _prng_idx, _hash_idx, _key) \ + rsa_encrypt_key_ex(_in, _inlen, _out, _outlen, _lparam, _lparamlen, _prng, _prng_idx, _hash_idx, LTC_PKCS_1_OAEP, _key) + +#define rsa_decrypt_key(_in, _inlen, _out, _outlen, _lparam, _lparamlen, _hash_idx, _stat, _key) \ + rsa_decrypt_key_ex(_in, _inlen, _out, _outlen, _lparam, _lparamlen, _hash_idx, LTC_PKCS_1_OAEP, _stat, _key) + +#define rsa_sign_hash(_in, _inlen, _out, _outlen, _prng, _prng_idx, _hash_idx, _saltlen, _key) \ + rsa_sign_hash_ex(_in, _inlen, _out, _outlen, LTC_PKCS_1_PSS, _prng, _prng_idx, _hash_idx, _saltlen, _key) + +#define rsa_verify_hash(_sig, _siglen, _hash, _hashlen, _hash_idx, _saltlen, _stat, _key) \ + rsa_verify_hash_ex(_sig, _siglen, _hash, _hashlen, LTC_PKCS_1_PSS, _hash_idx, _saltlen, _stat, _key) + +/* These can be switched between PKCS #1 v2.x and PKCS #1 v1.5 paddings */ +int rsa_encrypt_key_ex(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen, + const unsigned char *lparam, unsigned long lparamlen, + prng_state *prng, int prng_idx, int hash_idx, int padding, rsa_key *key); + +int rsa_decrypt_key_ex(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen, + const unsigned char *lparam, unsigned long lparamlen, + int hash_idx, int padding, + int *stat, rsa_key *key); + +int rsa_sign_hash_ex(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen, + int padding, + prng_state *prng, int prng_idx, + int hash_idx, unsigned long saltlen, + rsa_key *key); + +int rsa_verify_hash_ex(const unsigned char *sig, unsigned long siglen, + const unsigned char *hash, unsigned long hashlen, + int padding, + int hash_idx, unsigned long saltlen, + int *stat, rsa_key *key); + +/* PKCS #1 import/export */ +int rsa_export(unsigned char *out, unsigned long *outlen, int type, rsa_key *key); +int rsa_import(const unsigned char *in, unsigned long inlen, rsa_key *key); + +#endif + +/* ---- Katja ---- */ +#ifdef MKAT + +/* Min and Max KAT key sizes (in bits) */ +#define MIN_KAT_SIZE 1024 +#define MAX_KAT_SIZE 4096 + +/** Katja PKCS style key */ +typedef struct KAT_key { + /** Type of key, PK_PRIVATE or PK_PUBLIC */ + int type; + /** The private exponent */ + void *d; + /** The modulus */ + void *N; + /** The p factor of N */ + void *p; + /** The q factor of N */ + void *q; + /** The 1/q mod p CRT param */ + void *qP; + /** The d mod (p - 1) CRT param */ + void *dP; + /** The d mod (q - 1) CRT param */ + void *dQ; + /** The pq param */ + void *pq; +} katja_key; + +int katja_make_key(prng_state *prng, int wprng, int size, katja_key *key); + +int katja_exptmod(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen, int which, + katja_key *key); + +void katja_free(katja_key *key); + +/* These use PKCS #1 v2.0 padding */ +int katja_encrypt_key(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen, + const unsigned char *lparam, unsigned long lparamlen, + prng_state *prng, int prng_idx, int hash_idx, katja_key *key); + +int katja_decrypt_key(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen, + const unsigned char *lparam, unsigned long lparamlen, + int hash_idx, int *stat, + katja_key *key); + +/* PKCS #1 import/export */ +int katja_export(unsigned char *out, unsigned long *outlen, int type, katja_key *key); +int katja_import(const unsigned char *in, unsigned long inlen, katja_key *key); + +#endif + +/* ---- ECC Routines ---- */ +#ifdef MECC + +/* size of our temp buffers for exported keys */ +#define ECC_BUF_SIZE 256 + +/* max private key size */ +#define ECC_MAXSIZE 66 + +/** Structure defines a NIST GF(p) curve */ +typedef struct { + /** The size of the curve in octets */ + int size; + + /** name of curve */ + char *name; + + /** The prime that defines the field the curve is in (encoded in hex) */ + char *prime; + + /** The fields B param (hex) */ + char *B; + + /** The order of the curve (hex) */ + char *order; + + /** The x co-ordinate of the base point on the curve (hex) */ + char *Gx; + + /** The y co-ordinate of the base point on the curve (hex) */ + char *Gy; +} ltc_ecc_set_type; + +/** A point on a ECC curve, stored in Jacbobian format such that (x,y,z) => (x/z^2, y/z^3, 1) when interpretted as affine */ +typedef struct { + /** The x co-ordinate */ + void *x; + + /** The y co-ordinate */ + void *y; + + /** The z co-ordinate */ + void *z; +} ecc_point; + +/** An ECC key */ +typedef struct { + /** Type of key, PK_PRIVATE or PK_PUBLIC */ + int type; + + /** Index into the ltc_ecc_sets[] for the parameters of this curve; if -1, then this key is using user supplied curve in dp */ + int idx; + + /** pointer to domain parameters; either points to NIST curves (identified by idx >= 0) or user supplied curve */ + const ltc_ecc_set_type *dp; + + /** The public key */ + ecc_point pubkey; + + /** The private key */ + void *k; +} ecc_key; + +/** the ECC params provided */ +extern const ltc_ecc_set_type ltc_ecc_sets[]; + +int ecc_test(void); +void ecc_sizes(int *low, int *high); +int ecc_get_size(ecc_key *key); + +int ecc_make_key(prng_state *prng, int wprng, int keysize, ecc_key *key); +int ecc_make_key_ex(prng_state *prng, int wprng, ecc_key *key, const ltc_ecc_set_type *dp); +void ecc_free(ecc_key *key); + +int ecc_export(unsigned char *out, unsigned long *outlen, int type, ecc_key *key); +int ecc_import(const unsigned char *in, unsigned long inlen, ecc_key *key); +int ecc_import_ex(const unsigned char *in, unsigned long inlen, ecc_key *key, const ltc_ecc_set_type *dp); + +int ecc_ansi_x963_export(ecc_key *key, unsigned char *out, unsigned long *outlen); +int ecc_ansi_x963_import(const unsigned char *in, unsigned long inlen, ecc_key *key); +int ecc_ansi_x963_import_ex(const unsigned char *in, unsigned long inlen, ecc_key *key, ltc_ecc_set_type *dp); + +int ecc_shared_secret(ecc_key *private_key, ecc_key *public_key, + unsigned char *out, unsigned long *outlen); + +int ecc_encrypt_key(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen, + prng_state *prng, int wprng, int hash, + ecc_key *key); + +int ecc_decrypt_key(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen, + ecc_key *key); + +int ecc_sign_hash(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen, + prng_state *prng, int wprng, ecc_key *key); + +int ecc_verify_hash(const unsigned char *sig, unsigned long siglen, + const unsigned char *hash, unsigned long hashlen, + int *stat, ecc_key *key); + +/* low level functions */ +ecc_point *ltc_ecc_new_point(void); +void ltc_ecc_del_point(ecc_point *p); +int ltc_ecc_is_valid_idx(int n); + +/* point ops (mp == montgomery digit) */ +#if !defined(MECC_ACCEL) || defined(LTM_DESC) || defined(GMP_DESC) +/* R = 2P */ +int ltc_ecc_projective_dbl_point(ecc_point *P, ecc_point *R, void *modulus, void *mp); + +/* R = P + Q */ +int ltc_ecc_projective_add_point(ecc_point *P, ecc_point *Q, ecc_point *R, void *modulus, void *mp); +#endif + +#if defined(MECC_FP) +int ltc_ecc_fp_mulmod(void *k, ecc_point *G, ecc_point *R, void *modulus, int map); +int ltc_ecc_fp_save_state(unsigned char **out, unsigned long *outlen); +int ltc_ecc_fp_restore_state(unsigned char *in, unsigned long inlen); +void ltc_ecc_fp_free(void); +#endif + +/* R = kG */ +int ltc_ecc_mulmod(void *k, ecc_point *G, ecc_point *R, void *modulus, int map); + +#ifdef LTC_ECC_SHAMIR +/* kA*A + kB*B = C */ +int ltc_ecc_mul2add(ecc_point *A, void *kA, + ecc_point *B, void *kB, + ecc_point *C, + void *modulus); + +#ifdef MECC_FP +int ltc_ecc_fp_mul2add(ecc_point *A, void *kA, + ecc_point *B, void *kB, + ecc_point *C, void *modulus); +#endif + +#endif + + +/* map P to affine from projective */ +int ltc_ecc_map(ecc_point *P, void *modulus, void *mp); + +#endif + +#ifdef MDSA + +/* Max diff between group and modulus size in bytes */ +#define MDSA_DELTA 512 + +/* Max DSA group size in bytes (default allows 4k-bit groups) */ +#define MDSA_MAX_GROUP 512 + +/** DSA key structure */ +typedef struct { + /** The key type, PK_PRIVATE or PK_PUBLIC */ + int type; + + /** The order of the sub-group used in octets */ + int qord; + + /** The generator */ + void *g; + + /** The prime used to generate the sub-group */ + void *q; + + /** The large prime that generats the field the contains the sub-group */ + void *p; + + /** The private key */ + void *x; + + /** The public key */ + void *y; +} dsa_key; + +int dsa_make_key(prng_state *prng, int wprng, int group_size, int modulus_size, dsa_key *key); +void dsa_free(dsa_key *key); + +int dsa_sign_hash_raw(const unsigned char *in, unsigned long inlen, + void *r, void *s, + prng_state *prng, int wprng, dsa_key *key); + +int dsa_sign_hash(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen, + prng_state *prng, int wprng, dsa_key *key); + +int dsa_verify_hash_raw( void *r, void *s, + const unsigned char *hash, unsigned long hashlen, + int *stat, dsa_key *key); + +int dsa_verify_hash(const unsigned char *sig, unsigned long siglen, + const unsigned char *hash, unsigned long hashlen, + int *stat, dsa_key *key); + +int dsa_encrypt_key(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen, + prng_state *prng, int wprng, int hash, + dsa_key *key); + +int dsa_decrypt_key(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen, + dsa_key *key); + +int dsa_import(const unsigned char *in, unsigned long inlen, dsa_key *key); +int dsa_export(unsigned char *out, unsigned long *outlen, int type, dsa_key *key); +int dsa_verify_key(dsa_key *key, int *stat); + +int dsa_shared_secret(void *private_key, void *base, + dsa_key *public_key, + unsigned char *out, unsigned long *outlen); +#endif + +#ifdef LTC_DER +/* DER handling */ + +enum { + LTC_ASN1_EOL, + LTC_ASN1_BOOLEAN, + LTC_ASN1_INTEGER, + LTC_ASN1_SHORT_INTEGER, + LTC_ASN1_BIT_STRING, + LTC_ASN1_OCTET_STRING, + LTC_ASN1_NULL, + LTC_ASN1_OBJECT_IDENTIFIER, + LTC_ASN1_IA5_STRING, + LTC_ASN1_PRINTABLE_STRING, + LTC_ASN1_UTF8_STRING, + LTC_ASN1_UTCTIME, + LTC_ASN1_CHOICE, + LTC_ASN1_SEQUENCE, + LTC_ASN1_SET, + LTC_ASN1_SETOF +}; + +/** A LTC ASN.1 list type */ +typedef struct ltc_asn1_list_ { + /** The LTC ASN.1 enumerated type identifier */ + int type; + /** The data to encode or place for decoding */ + void *data; + /** The size of the input or resulting output */ + unsigned long size; + /** The used flag, this is used by the CHOICE ASN.1 type to indicate which choice was made */ + int used; + /** prev/next entry in the list */ + struct ltc_asn1_list_ *prev, *next, *child, *parent; +} ltc_asn1_list; + +#define LTC_SET_ASN1(list, index, Type, Data, Size) \ + do { \ + int LTC_MACRO_temp = (index); \ + ltc_asn1_list *LTC_MACRO_list = (list); \ + LTC_MACRO_list[LTC_MACRO_temp].type = (Type); \ + LTC_MACRO_list[LTC_MACRO_temp].data = (void*)(Data); \ + LTC_MACRO_list[LTC_MACRO_temp].size = (Size); \ + LTC_MACRO_list[LTC_MACRO_temp].used = 0; \ + } while (0); + +/* SEQUENCE */ +int der_encode_sequence_ex(ltc_asn1_list *list, unsigned long inlen, + unsigned char *out, unsigned long *outlen, int type_of); + +#define der_encode_sequence(list, inlen, out, outlen) der_encode_sequence_ex(list, inlen, out, outlen, LTC_ASN1_SEQUENCE) + +int der_decode_sequence_ex(const unsigned char *in, unsigned long inlen, + ltc_asn1_list *list, unsigned long outlen, int ordered); + +#define der_decode_sequence(in, inlen, list, outlen) der_decode_sequence_ex(in, inlen, list, outlen, 1) + +int der_length_sequence(ltc_asn1_list *list, unsigned long inlen, + unsigned long *outlen); + +/* SET */ +#define der_decode_set(in, inlen, list, outlen) der_decode_sequence_ex(in, inlen, list, outlen, 0) +#define der_length_set der_length_sequence +int der_encode_set(ltc_asn1_list *list, unsigned long inlen, + unsigned char *out, unsigned long *outlen); + +int der_encode_setof(ltc_asn1_list *list, unsigned long inlen, + unsigned char *out, unsigned long *outlen); + +/* VA list handy helpers with triplets of */ +int der_encode_sequence_multi(unsigned char *out, unsigned long *outlen, ...); +int der_decode_sequence_multi(const unsigned char *in, unsigned long inlen, ...); + +/* FLEXI DECODER handle unknown list decoder */ +int der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc_asn1_list **out); +void der_free_sequence_flexi(ltc_asn1_list *list); +void der_sequence_free(ltc_asn1_list *in); + +/* BOOLEAN */ +int der_length_boolean(unsigned long *outlen); +int der_encode_boolean(int in, + unsigned char *out, unsigned long *outlen); +int der_decode_boolean(const unsigned char *in, unsigned long inlen, + int *out); +/* INTEGER */ +int der_encode_integer(void *num, unsigned char *out, unsigned long *outlen); +int der_decode_integer(const unsigned char *in, unsigned long inlen, void *num); +int der_length_integer(void *num, unsigned long *len); + +/* INTEGER -- handy for 0..2^32-1 values */ +int der_decode_short_integer(const unsigned char *in, unsigned long inlen, unsigned long *num); +int der_encode_short_integer(unsigned long num, unsigned char *out, unsigned long *outlen); +int der_length_short_integer(unsigned long num, unsigned long *outlen); + +/* BIT STRING */ +int der_encode_bit_string(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen); +int der_decode_bit_string(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen); +int der_length_bit_string(unsigned long nbits, unsigned long *outlen); + +/* OCTET STRING */ +int der_encode_octet_string(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen); +int der_decode_octet_string(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen); +int der_length_octet_string(unsigned long noctets, unsigned long *outlen); + +/* OBJECT IDENTIFIER */ +int der_encode_object_identifier(unsigned long *words, unsigned long nwords, + unsigned char *out, unsigned long *outlen); +int der_decode_object_identifier(const unsigned char *in, unsigned long inlen, + unsigned long *words, unsigned long *outlen); +int der_length_object_identifier(unsigned long *words, unsigned long nwords, unsigned long *outlen); +unsigned long der_object_identifier_bits(unsigned long x); + +/* IA5 STRING */ +int der_encode_ia5_string(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen); +int der_decode_ia5_string(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen); +int der_length_ia5_string(const unsigned char *octets, unsigned long noctets, unsigned long *outlen); + +int der_ia5_char_encode(int c); +int der_ia5_value_decode(int v); + +/* Printable STRING */ +int der_encode_printable_string(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen); +int der_decode_printable_string(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen); +int der_length_printable_string(const unsigned char *octets, unsigned long noctets, unsigned long *outlen); + +int der_printable_char_encode(int c); +int der_printable_value_decode(int v); + +/* UTF-8 */ +#if (defined(SIZE_MAX) || __STDC_VERSION__ >= 199901L || defined(WCHAR_MAX) || defined(_WCHAR_T) || defined(_WCHAR_T_DEFINED)) && !defined(LTC_NO_WCHAR) +#include +#else +typedef ulong32 wchar_t; +#endif + +int der_encode_utf8_string(const wchar_t *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen); + +int der_decode_utf8_string(const unsigned char *in, unsigned long inlen, + wchar_t *out, unsigned long *outlen); +unsigned long der_utf8_charsize(const wchar_t c); +int der_length_utf8_string(const wchar_t *in, unsigned long noctets, unsigned long *outlen); + + +/* CHOICE */ +int der_decode_choice(const unsigned char *in, unsigned long *inlen, + ltc_asn1_list *list, unsigned long outlen); + +/* UTCTime */ +typedef struct { + unsigned YY, /* year */ + MM, /* month */ + DD, /* day */ + hh, /* hour */ + mm, /* minute */ + ss, /* second */ + off_dir, /* timezone offset direction 0 == +, 1 == - */ + off_hh, /* timezone offset hours */ + off_mm; /* timezone offset minutes */ +} ltc_utctime; + +int der_encode_utctime(ltc_utctime *utctime, + unsigned char *out, unsigned long *outlen); + +int der_decode_utctime(const unsigned char *in, unsigned long *inlen, + ltc_utctime *out); + +int der_length_utctime(ltc_utctime *utctime, unsigned long *outlen); + + +#endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/plugins/pro1_data_zip/ltc/headers/tomcrypt_pkcs.h b/src/plugins/pro1_data_zip/ltc/headers/tomcrypt_pkcs.h new file mode 100644 index 0000000..2d7ebf2 --- /dev/null +++ b/src/plugins/pro1_data_zip/ltc/headers/tomcrypt_pkcs.h @@ -0,0 +1,89 @@ +/* PKCS Header Info */ + +/* ===> PKCS #1 -- RSA Cryptography <=== */ +#ifdef PKCS_1 + +enum ltc_pkcs_1_v1_5_blocks +{ + LTC_PKCS_1_EMSA = 1, /* Block type 1 (PKCS #1 v1.5 signature padding) */ + LTC_PKCS_1_EME = 2 /* Block type 2 (PKCS #1 v1.5 encryption padding) */ +}; + +enum ltc_pkcs_1_paddings +{ + LTC_PKCS_1_V1_5 = 1, /* PKCS #1 v1.5 padding (\sa ltc_pkcs_1_v1_5_blocks) */ + LTC_PKCS_1_OAEP = 2, /* PKCS #1 v2.0 encryption padding */ + LTC_PKCS_1_PSS = 3 /* PKCS #1 v2.1 signature padding */ +}; + +int pkcs_1_mgf1( int hash_idx, + const unsigned char *seed, unsigned long seedlen, + unsigned char *mask, unsigned long masklen); + +int pkcs_1_i2osp(void *n, unsigned long modulus_len, unsigned char *out); +int pkcs_1_os2ip(void *n, unsigned char *in, unsigned long inlen); + +/* *** v1.5 padding */ +int pkcs_1_v1_5_encode(const unsigned char *msg, + unsigned long msglen, + int block_type, + unsigned long modulus_bitlen, + prng_state *prng, + int prng_idx, + unsigned char *out, + unsigned long *outlen); + +int pkcs_1_v1_5_decode(const unsigned char *msg, + unsigned long msglen, + int block_type, + unsigned long modulus_bitlen, + unsigned char *out, + unsigned long *outlen, + int *is_valid); + +/* *** v2.1 padding */ +int pkcs_1_oaep_encode(const unsigned char *msg, unsigned long msglen, + const unsigned char *lparam, unsigned long lparamlen, + unsigned long modulus_bitlen, prng_state *prng, + int prng_idx, int hash_idx, + unsigned char *out, unsigned long *outlen); + +int pkcs_1_oaep_decode(const unsigned char *msg, unsigned long msglen, + const unsigned char *lparam, unsigned long lparamlen, + unsigned long modulus_bitlen, int hash_idx, + unsigned char *out, unsigned long *outlen, + int *res); + +int pkcs_1_pss_encode(const unsigned char *msghash, unsigned long msghashlen, + unsigned long saltlen, prng_state *prng, + int prng_idx, int hash_idx, + unsigned long modulus_bitlen, + unsigned char *out, unsigned long *outlen); + +int pkcs_1_pss_decode(const unsigned char *msghash, unsigned long msghashlen, + const unsigned char *sig, unsigned long siglen, + unsigned long saltlen, int hash_idx, + unsigned long modulus_bitlen, int *res); + +#endif /* PKCS_1 */ + +/* ===> PKCS #5 -- Password Based Cryptography <=== */ +#ifdef PKCS_5 + +/* Algorithm #1 (old) */ +int pkcs_5_alg1(const unsigned char *password, unsigned long password_len, + const unsigned char *salt, + int iteration_count, int hash_idx, + unsigned char *out, unsigned long *outlen); + +/* Algorithm #2 (new) */ +int pkcs_5_alg2(const unsigned char *password, unsigned long password_len, + const unsigned char *salt, unsigned long salt_len, + int iteration_count, int hash_idx, + unsigned char *out, unsigned long *outlen); + +#endif /* PKCS_5 */ + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/plugins/pro1_data_zip/ltc/headers/tomcrypt_prng.h b/src/plugins/pro1_data_zip/ltc/headers/tomcrypt_prng.h new file mode 100644 index 0000000..01382c9 --- /dev/null +++ b/src/plugins/pro1_data_zip/ltc/headers/tomcrypt_prng.h @@ -0,0 +1,199 @@ +/* ---- PRNG Stuff ---- */ +#ifdef YARROW +struct yarrow_prng { + int cipher, hash; + unsigned char pool[MAXBLOCKSIZE]; + symmetric_CTR ctr; + LTC_MUTEX_TYPE(prng_lock) +}; +#endif + +#ifdef RC4 +struct rc4_prng { + int x, y; + unsigned char buf[256]; +}; +#endif + +#ifdef FORTUNA +struct fortuna_prng { + hash_state pool[FORTUNA_POOLS]; /* the pools */ + + symmetric_key skey; + + unsigned char K[32], /* the current key */ + IV[16]; /* IV for CTR mode */ + + unsigned long pool_idx, /* current pool we will add to */ + pool0_len, /* length of 0'th pool */ + wd; + + ulong64 reset_cnt; /* number of times we have reset */ + LTC_MUTEX_TYPE(prng_lock) +}; +#endif + +#ifdef SOBER128 +struct sober128_prng { + ulong32 R[17], /* Working storage for the shift register */ + initR[17], /* saved register contents */ + konst, /* key dependent constant */ + sbuf; /* partial word encryption buffer */ + + int nbuf, /* number of part-word stream bits buffered */ + flag, /* first add_entropy call or not? */ + set; /* did we call add_entropy to set key? */ + +}; +#endif + +typedef union Prng_state { + char dummy[1]; +#ifdef YARROW + struct yarrow_prng yarrow; +#endif +#ifdef RC4 + struct rc4_prng rc4; +#endif +#ifdef FORTUNA + struct fortuna_prng fortuna; +#endif +#ifdef SOBER128 + struct sober128_prng sober128; +#endif +} prng_state; + +/** PRNG descriptor */ +extern struct ltc_prng_descriptor { + /** Name of the PRNG */ + char *name; + /** size in bytes of exported state */ + int export_size; + /** Start a PRNG state + @param prng [out] The state to initialize + @return CRYPT_OK if successful + */ + int (*start)(prng_state *prng); + /** Add entropy to the PRNG + @param in The entropy + @param inlen Length of the entropy (octets)\ + @param prng The PRNG state + @return CRYPT_OK if successful + */ + int (*add_entropy)(const unsigned char *in, unsigned long inlen, prng_state *prng); + /** Ready a PRNG state to read from + @param prng The PRNG state to ready + @return CRYPT_OK if successful + */ + int (*ready)(prng_state *prng); + /** Read from the PRNG + @param out [out] Where to store the data + @param outlen Length of data desired (octets) + @param prng The PRNG state to read from + @return Number of octets read + */ + unsigned long (*read)(unsigned char *out, unsigned long outlen, prng_state *prng); + /** Terminate a PRNG state + @param prng The PRNG state to terminate + @return CRYPT_OK if successful + */ + int (*done)(prng_state *prng); + /** Export a PRNG state + @param out [out] The destination for the state + @param outlen [in/out] The max size and resulting size of the PRNG state + @param prng The PRNG to export + @return CRYPT_OK if successful + */ + int (*pexport)(unsigned char *out, unsigned long *outlen, prng_state *prng); + /** Import a PRNG state + @param in The data to import + @param inlen The length of the data to import (octets) + @param prng The PRNG to initialize/import + @return CRYPT_OK if successful + */ + int (*pimport)(const unsigned char *in, unsigned long inlen, prng_state *prng); + /** Self-test the PRNG + @return CRYPT_OK if successful, CRYPT_NOP if self-testing has been disabled + */ + int (*test)(void); +} prng_descriptor[]; + +#ifdef YARROW +int yarrow_start(prng_state *prng); +int yarrow_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng); +int yarrow_ready(prng_state *prng); +unsigned long yarrow_read(unsigned char *out, unsigned long outlen, prng_state *prng); +int yarrow_done(prng_state *prng); +int yarrow_export(unsigned char *out, unsigned long *outlen, prng_state *prng); +int yarrow_import(const unsigned char *in, unsigned long inlen, prng_state *prng); +int yarrow_test(void); +extern const struct ltc_prng_descriptor yarrow_desc; +#endif + +#ifdef FORTUNA +int fortuna_start(prng_state *prng); +int fortuna_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng); +int fortuna_ready(prng_state *prng); +unsigned long fortuna_read(unsigned char *out, unsigned long outlen, prng_state *prng); +int fortuna_done(prng_state *prng); +int fortuna_export(unsigned char *out, unsigned long *outlen, prng_state *prng); +int fortuna_import(const unsigned char *in, unsigned long inlen, prng_state *prng); +int fortuna_test(void); +extern const struct ltc_prng_descriptor fortuna_desc; +#endif + +#ifdef RC4 +int rc4_start(prng_state *prng); +int rc4_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng); +int rc4_ready(prng_state *prng); +unsigned long rc4_read(unsigned char *out, unsigned long outlen, prng_state *prng); +int rc4_done(prng_state *prng); +int rc4_export(unsigned char *out, unsigned long *outlen, prng_state *prng); +int rc4_import(const unsigned char *in, unsigned long inlen, prng_state *prng); +int rc4_test(void); +extern const struct ltc_prng_descriptor rc4_desc; +#endif + +#ifdef SPRNG +int sprng_start(prng_state *prng); +int sprng_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng); +int sprng_ready(prng_state *prng); +unsigned long sprng_read(unsigned char *out, unsigned long outlen, prng_state *prng); +int sprng_done(prng_state *prng); +int sprng_export(unsigned char *out, unsigned long *outlen, prng_state *prng); +int sprng_import(const unsigned char *in, unsigned long inlen, prng_state *prng); +int sprng_test(void); +extern const struct ltc_prng_descriptor sprng_desc; +#endif + +#ifdef SOBER128 +int sober128_start(prng_state *prng); +int sober128_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng); +int sober128_ready(prng_state *prng); +unsigned long sober128_read(unsigned char *out, unsigned long outlen, prng_state *prng); +int sober128_done(prng_state *prng); +int sober128_export(unsigned char *out, unsigned long *outlen, prng_state *prng); +int sober128_import(const unsigned char *in, unsigned long inlen, prng_state *prng); +int sober128_test(void); +extern const struct ltc_prng_descriptor sober128_desc; +#endif + +int find_prng(const char *name); +int register_prng(const struct ltc_prng_descriptor *prng); +int unregister_prng(const struct ltc_prng_descriptor *prng); +int prng_is_valid(int idx); +LTC_MUTEX_PROTO(ltc_prng_mutex) + +/* Slow RNG you **might** be able to use to seed a PRNG with. Be careful as this + * might not work on all platforms as planned + */ +unsigned long rng_get_bytes(unsigned char *out, + unsigned long outlen, + void (*callback)(void)); + +int rng_make_prng(int bits, int wprng, prng_state *prng, void (*callback)(void)); + + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/plugins/pro1_data_zip/ltc/headers/tommath.h b/src/plugins/pro1_data_zip/ltc/headers/tommath.h new file mode 100644 index 0000000..ee5da86 --- /dev/null +++ b/src/plugins/pro1_data_zip/ltc/headers/tommath.h @@ -0,0 +1,615 @@ +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * SPDX-License-Identifier: Unlicense + */ +#ifndef BN_H_ +#define BN_H_ + +#include +#include +#include +#include + +#include "tommath_class.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* MS Visual C++ doesn't have a 128bit type for words, so fall back to 32bit MPI's (where words are 64bit) */ +#if defined(_MSC_VER) || defined(__LLP64__) || defined(__e2k__) || defined(__LCC__) +# define MP_32BIT +#endif + +/* detect 64-bit mode if possible */ +#if defined(__x86_64__) || defined(_M_X64) || defined(_M_AMD64) || \ + defined(__powerpc64__) || defined(__ppc64__) || defined(__PPC64__) || \ + defined(__s390x__) || defined(__arch64__) || defined(__aarch64__) || \ + defined(__sparcv9) || defined(__sparc_v9__) || defined(__sparc64__) || \ + defined(__ia64) || defined(__ia64__) || defined(__itanium__) || defined(_M_IA64) || \ + defined(__LP64__) || defined(_LP64) || defined(__64BIT__) +# if !(defined(MP_32BIT) || defined(MP_16BIT) || defined(MP_8BIT)) +# if defined(__GNUC__) +/* we support 128bit integers only via: __attribute__((mode(TI))) */ +# define MP_64BIT +# else +/* otherwise we fall back to MP_32BIT even on 64bit platforms */ +# define MP_32BIT +# endif +# endif +#endif + +/* some default configurations. + * + * A "mp_digit" must be able to hold DIGIT_BIT + 1 bits + * A "mp_word" must be able to hold 2*DIGIT_BIT + 1 bits + * + * At the very least a mp_digit must be able to hold 7 bits + * [any size beyond that is ok provided it doesn't overflow the data type] + */ +#ifdef MP_8BIT +typedef uint8_t mp_digit; +typedef uint16_t mp_word; +# define MP_SIZEOF_MP_DIGIT 1 +# ifdef DIGIT_BIT +# error You must not define DIGIT_BIT when using MP_8BIT +# endif +#elif defined(MP_16BIT) +typedef uint16_t mp_digit; +typedef uint32_t mp_word; +# define MP_SIZEOF_MP_DIGIT 2 +# ifdef DIGIT_BIT +# error You must not define DIGIT_BIT when using MP_16BIT +# endif +#elif defined(MP_64BIT) +/* for GCC only on supported platforms */ +typedef uint64_t mp_digit; +typedef unsigned long mp_word __attribute__((mode(TI))); +# define DIGIT_BIT 60 +#else +/* this is the default case, 28-bit digits */ + +/* this is to make porting into LibTomCrypt easier :-) */ +typedef uint32_t mp_digit; +typedef uint64_t mp_word; + +# ifdef MP_31BIT +/* this is an extension that uses 31-bit digits */ +# define DIGIT_BIT 31 +# else +/* default case is 28-bit digits, defines MP_28BIT as a handy macro to test */ +# define DIGIT_BIT 28 +# define MP_28BIT +# endif +#endif + +/* otherwise the bits per digit is calculated automatically from the size of a mp_digit */ +#ifndef DIGIT_BIT +# define DIGIT_BIT (((CHAR_BIT * MP_SIZEOF_MP_DIGIT) - 1)) /* bits per digit */ +typedef uint_least32_t mp_min_u32; +#else +typedef mp_digit mp_min_u32; +#endif + +#define MP_DIGIT_BIT DIGIT_BIT +#define MP_MASK ((((mp_digit)1)<<((mp_digit)DIGIT_BIT))-((mp_digit)1)) +#define MP_DIGIT_MAX MP_MASK + +/* equalities */ +#define MP_LT -1 /* less than */ +#define MP_EQ 0 /* equal to */ +#define MP_GT 1 /* greater than */ + +#define MP_ZPOS 0 /* positive integer */ +#define MP_NEG 1 /* negative */ + +#define MP_OKAY 0 /* ok result */ +#define MP_MEM -2 /* out of mem */ +#define MP_VAL -3 /* invalid input */ +#define MP_RANGE MP_VAL +#define MP_ITER -4 /* Max. iterations reached */ + +#define MP_YES 1 /* yes response */ +#define MP_NO 0 /* no response */ + +/* Primality generation flags */ +#define LTM_PRIME_BBS 0x0001 /* BBS style prime */ +#define LTM_PRIME_SAFE 0x0002 /* Safe prime (p-1)/2 == prime */ +#define LTM_PRIME_2MSB_ON 0x0008 /* force 2nd MSB to 1 */ + +typedef int mp_err; + +/* you'll have to tune these... */ +extern int KARATSUBA_MUL_CUTOFF, + KARATSUBA_SQR_CUTOFF, + TOOM_MUL_CUTOFF, + TOOM_SQR_CUTOFF; + +/* define this to use lower memory usage routines (exptmods mostly) */ +/* #define MP_LOW_MEM */ + +/* default precision */ +#ifndef MP_PREC +# ifndef MP_LOW_MEM +# define MP_PREC 32 /* default digits of precision */ +# else +# define MP_PREC 8 /* default digits of precision */ +# endif +#endif + +/* size of comba arrays, should be at least 2 * 2**(BITS_PER_WORD - BITS_PER_DIGIT*2) */ +#define MP_WARRAY (1u << (((sizeof(mp_word) * CHAR_BIT) - (2 * DIGIT_BIT)) + 1)) + +/* the infamous mp_int structure */ +typedef struct { + int used, alloc, sign; + mp_digit *dp; +} mp_int; + +/* callback for mp_prime_random, should fill dst with random bytes and return how many read [upto len] */ +typedef int ltm_prime_callback(unsigned char *dst, int len, void *dat); + + +#define USED(m) ((m)->used) +#define DIGIT(m, k) ((m)->dp[(k)]) +#define SIGN(m) ((m)->sign) + +/* error code to char* string */ +const char *mp_error_to_string(int code); + +/* ---> init and deinit bignum functions <--- */ +/* init a bignum */ +int mp_init(mp_int *a); + +/* free a bignum */ +void mp_clear(mp_int *a); + +/* init a null terminated series of arguments */ +int mp_init_multi(mp_int *mp, ...); + +/* clear a null terminated series of arguments */ +void mp_clear_multi(mp_int *mp, ...); + +/* exchange two ints */ +void mp_exch(mp_int *a, mp_int *b); + +/* shrink ram required for a bignum */ +int mp_shrink(mp_int *a); + +/* grow an int to a given size */ +int mp_grow(mp_int *a, int size); + +/* init to a given number of digits */ +int mp_init_size(mp_int *a, int size); + +/* ---> Basic Manipulations <--- */ +#define mp_iszero(a) (((a)->used == 0) ? MP_YES : MP_NO) +#define mp_iseven(a) ((((a)->used == 0) || (((a)->dp[0] & 1u) == 0u)) ? MP_YES : MP_NO) +#define mp_isodd(a) ((((a)->used > 0) && (((a)->dp[0] & 1u) == 1u)) ? MP_YES : MP_NO) +#define mp_isneg(a) (((a)->sign != MP_ZPOS) ? MP_YES : MP_NO) + +/* set to zero */ +void mp_zero(mp_int *a); + +/* set to a digit */ +void mp_set(mp_int *a, mp_digit b); + +/* set a double */ +int mp_set_double(mp_int *a, double b); + +/* set a 32-bit const */ +int mp_set_int(mp_int *a, unsigned long b); + +/* set a platform dependent unsigned long value */ +int mp_set_long(mp_int *a, unsigned long b); + +/* set a platform dependent unsigned long long value */ +int mp_set_long_long(mp_int *a, unsigned long long b); + +/* get a double */ +double mp_get_double(const mp_int *a); + +/* get a 32-bit value */ +unsigned long mp_get_int(const mp_int *a); + +/* get a platform dependent unsigned long value */ +unsigned long mp_get_long(const mp_int *a); + +/* get a platform dependent unsigned long long value */ +unsigned long long mp_get_long_long(const mp_int *a); + +/* initialize and set a digit */ +int mp_init_set(mp_int *a, mp_digit b); + +/* initialize and set 32-bit value */ +int mp_init_set_int(mp_int *a, unsigned long b); + +/* copy, b = a */ +int mp_copy(const mp_int *a, mp_int *b); + +/* inits and copies, a = b */ +int mp_init_copy(mp_int *a, const mp_int *b); + +/* trim unused digits */ +void mp_clamp(mp_int *a); + +/* import binary data */ +int mp_import(mp_int *rop, size_t count, int order, size_t size, int endian, size_t nails, const void *op); + +/* export binary data */ +int mp_export(void *rop, size_t *countp, int order, size_t size, int endian, size_t nails, const mp_int *op); + +/* ---> digit manipulation <--- */ + +/* right shift by "b" digits */ +void mp_rshd(mp_int *a, int b); + +/* left shift by "b" digits */ +int mp_lshd(mp_int *a, int b); + +/* c = a / 2**b, implemented as c = a >> b */ +int mp_div_2d(const mp_int *a, int b, mp_int *c, mp_int *d); + +/* b = a/2 */ +int mp_div_2(const mp_int *a, mp_int *b); + +/* c = a * 2**b, implemented as c = a << b */ +int mp_mul_2d(const mp_int *a, int b, mp_int *c); + +/* b = a*2 */ +int mp_mul_2(const mp_int *a, mp_int *b); + +/* c = a mod 2**b */ +int mp_mod_2d(const mp_int *a, int b, mp_int *c); + +/* computes a = 2**b */ +int mp_2expt(mp_int *a, int b); + +/* Counts the number of lsbs which are zero before the first zero bit */ +int mp_cnt_lsb(const mp_int *a); + +/* I Love Earth! */ + +/* makes a pseudo-random mp_int of a given size */ +int mp_rand(mp_int *a, int digits); +/* makes a pseudo-random small int of a given size */ +int mp_rand_digit(mp_digit *r); + +#ifdef MP_PRNG_ENABLE_LTM_RNG +/* A last resort to provide random data on systems without any of the other + * implemented ways to gather entropy. + * It is compatible with `rng_get_bytes()` from libtomcrypt so you could + * provide that one and then set `ltm_rng = rng_get_bytes;` */ +extern unsigned long (*ltm_rng)(unsigned char *out, unsigned long outlen, void (*callback)(void)); +extern void (*ltm_rng_callback)(void); +#endif + +/* ---> binary operations <--- */ +/* c = a XOR b */ +int mp_xor(const mp_int *a, const mp_int *b, mp_int *c); + +/* c = a OR b */ +int mp_or(const mp_int *a, const mp_int *b, mp_int *c); + +/* c = a AND b */ +int mp_and(const mp_int *a, const mp_int *b, mp_int *c); + +/* Checks the bit at position b and returns MP_YES + if the bit is 1, MP_NO if it is 0 and MP_VAL + in case of error */ +int mp_get_bit(const mp_int *a, int b); + +/* c = a XOR b (two complement) */ +int mp_tc_xor(const mp_int *a, const mp_int *b, mp_int *c); + +/* c = a OR b (two complement) */ +int mp_tc_or(const mp_int *a, const mp_int *b, mp_int *c); + +/* c = a AND b (two complement) */ +int mp_tc_and(const mp_int *a, const mp_int *b, mp_int *c); + +/* right shift (two complement) */ +int mp_tc_div_2d(const mp_int *a, int b, mp_int *c); + +/* ---> Basic arithmetic <--- */ + +/* b = ~a */ +int mp_complement(const mp_int *a, mp_int *b); + +/* b = -a */ +int mp_neg(const mp_int *a, mp_int *b); + +/* b = |a| */ +int mp_abs(const mp_int *a, mp_int *b); + +/* compare a to b */ +int mp_cmp(const mp_int *a, const mp_int *b); + +/* compare |a| to |b| */ +int mp_cmp_mag(const mp_int *a, const mp_int *b); + +/* c = a + b */ +int mp_add(const mp_int *a, const mp_int *b, mp_int *c); + +/* c = a - b */ +int mp_sub(const mp_int *a, const mp_int *b, mp_int *c); + +/* c = a * b */ +int mp_mul(const mp_int *a, const mp_int *b, mp_int *c); + +/* b = a*a */ +int mp_sqr(const mp_int *a, mp_int *b); + +/* a/b => cb + d == a */ +int mp_div(const mp_int *a, const mp_int *b, mp_int *c, mp_int *d); + +/* c = a mod b, 0 <= c < b */ +int mp_mod(const mp_int *a, const mp_int *b, mp_int *c); + +/* ---> single digit functions <--- */ + +/* compare against a single digit */ +int mp_cmp_d(const mp_int *a, mp_digit b); + +/* c = a + b */ +int mp_add_d(const mp_int *a, mp_digit b, mp_int *c); + +/* c = a - b */ +int mp_sub_d(const mp_int *a, mp_digit b, mp_int *c); + +/* c = a * b */ +int mp_mul_d(const mp_int *a, mp_digit b, mp_int *c); + +/* a/b => cb + d == a */ +int mp_div_d(const mp_int *a, mp_digit b, mp_int *c, mp_digit *d); + +/* a/3 => 3c + d == a */ +int mp_div_3(const mp_int *a, mp_int *c, mp_digit *d); + +/* c = a**b */ +int mp_expt_d(const mp_int *a, mp_digit b, mp_int *c); +int mp_expt_d_ex(const mp_int *a, mp_digit b, mp_int *c, int fast); + +/* c = a mod b, 0 <= c < b */ +int mp_mod_d(const mp_int *a, mp_digit b, mp_digit *c); + +/* ---> number theory <--- */ + +/* d = a + b (mod c) */ +int mp_addmod(const mp_int *a, const mp_int *b, const mp_int *c, mp_int *d); + +/* d = a - b (mod c) */ +int mp_submod(const mp_int *a, const mp_int *b, const mp_int *c, mp_int *d); + +/* d = a * b (mod c) */ +int mp_mulmod(const mp_int *a, const mp_int *b, const mp_int *c, mp_int *d); + +/* c = a * a (mod b) */ +int mp_sqrmod(const mp_int *a, const mp_int *b, mp_int *c); + +/* c = 1/a (mod b) */ +int mp_invmod(const mp_int *a, const mp_int *b, mp_int *c); + +/* c = (a, b) */ +int mp_gcd(const mp_int *a, const mp_int *b, mp_int *c); + +/* produces value such that U1*a + U2*b = U3 */ +int mp_exteuclid(const mp_int *a, const mp_int *b, mp_int *U1, mp_int *U2, mp_int *U3); + +/* c = [a, b] or (a*b)/(a, b) */ +int mp_lcm(const mp_int *a, const mp_int *b, mp_int *c); + +/* finds one of the b'th root of a, such that |c|**b <= |a| + * + * returns error if a < 0 and b is even + */ +int mp_n_root(const mp_int *a, mp_digit b, mp_int *c); +int mp_n_root_ex(const mp_int *a, mp_digit b, mp_int *c, int fast); + +/* special sqrt algo */ +int mp_sqrt(const mp_int *arg, mp_int *ret); + +/* special sqrt (mod prime) */ +int mp_sqrtmod_prime(const mp_int *n, const mp_int *prime, mp_int *ret); + +/* is number a square? */ +int mp_is_square(const mp_int *arg, int *ret); + +/* computes the jacobi c = (a | n) (or Legendre if b is prime) */ +int mp_jacobi(const mp_int *a, const mp_int *n, int *c); + +/* computes the Kronecker symbol c = (a | p) (like jacobi() but with {a,p} in Z */ +int mp_kronecker(const mp_int *a, const mp_int *p, int *c); + +/* used to setup the Barrett reduction for a given modulus b */ +int mp_reduce_setup(mp_int *a, const mp_int *b); + +/* Barrett Reduction, computes a (mod b) with a precomputed value c + * + * Assumes that 0 < x <= m*m, note if 0 > x > -(m*m) then you can merely + * compute the reduction as -1 * mp_reduce(mp_abs(x)) [pseudo code]. + */ +int mp_reduce(mp_int *x, const mp_int *m, const mp_int *mu); + +/* setups the montgomery reduction */ +int mp_montgomery_setup(const mp_int *n, mp_digit *rho); + +/* computes a = B**n mod b without division or multiplication useful for + * normalizing numbers in a Montgomery system. + */ +int mp_montgomery_calc_normalization(mp_int *a, const mp_int *b); + +/* computes x/R == x (mod N) via Montgomery Reduction */ +int mp_montgomery_reduce(mp_int *x, const mp_int *n, mp_digit rho); + +/* returns 1 if a is a valid DR modulus */ +int mp_dr_is_modulus(const mp_int *a); + +/* sets the value of "d" required for mp_dr_reduce */ +void mp_dr_setup(const mp_int *a, mp_digit *d); + +/* reduces a modulo n using the Diminished Radix method */ +int mp_dr_reduce(mp_int *x, const mp_int *n, mp_digit k); + +/* returns true if a can be reduced with mp_reduce_2k */ +int mp_reduce_is_2k(const mp_int *a); + +/* determines k value for 2k reduction */ +int mp_reduce_2k_setup(const mp_int *a, mp_digit *d); + +/* reduces a modulo b where b is of the form 2**p - k [0 <= a] */ +int mp_reduce_2k(mp_int *a, const mp_int *n, mp_digit d); + +/* returns true if a can be reduced with mp_reduce_2k_l */ +int mp_reduce_is_2k_l(const mp_int *a); + +/* determines k value for 2k reduction */ +int mp_reduce_2k_setup_l(const mp_int *a, mp_int *d); + +/* reduces a modulo b where b is of the form 2**p - k [0 <= a] */ +int mp_reduce_2k_l(mp_int *a, const mp_int *n, const mp_int *d); + +/* Y = G**X (mod P) */ +int mp_exptmod(const mp_int *G, const mp_int *X, const mp_int *P, mp_int *Y); + +/* ---> Primes <--- */ + +/* number of primes */ +#ifdef MP_8BIT +# define PRIME_SIZE 31 +#else +# define PRIME_SIZE 256 +#endif + +/* table of first PRIME_SIZE primes */ +extern const mp_digit ltm_prime_tab[PRIME_SIZE]; + +/* result=1 if a is divisible by one of the first PRIME_SIZE primes */ +int mp_prime_is_divisible(const mp_int *a, int *result); + +/* performs one Fermat test of "a" using base "b". + * Sets result to 0 if composite or 1 if probable prime + */ +int mp_prime_fermat(const mp_int *a, const mp_int *b, int *result); + +/* performs one Miller-Rabin test of "a" using base "b". + * Sets result to 0 if composite or 1 if probable prime + */ +int mp_prime_miller_rabin(const mp_int *a, const mp_int *b, int *result); + +/* This gives [for a given bit size] the number of trials required + * such that Miller-Rabin gives a prob of failure lower than 2^-96 + */ +int mp_prime_rabin_miller_trials(int size); + +/* performs one strong Lucas-Selfridge test of "a". + * Sets result to 0 if composite or 1 if probable prime + */ +int mp_prime_strong_lucas_selfridge(const mp_int *a, int *result); + +/* performs one Frobenius test of "a" as described by Paul Underwood. + * Sets result to 0 if composite or 1 if probable prime + */ +int mp_prime_frobenius_underwood(const mp_int *N, int *result); + +/* performs t random rounds of Miller-Rabin on "a" additional to + * bases 2 and 3. Also performs an initial sieve of trial + * division. Determines if "a" is prime with probability + * of error no more than (1/4)**t. + * Both a strong Lucas-Selfridge to complete the BPSW test + * and a separate Frobenius test are available at compile time. + * With t<0 a deterministic test is run for primes up to + * 318665857834031151167461. With t<13 (abs(t)-13) additional + * tests with sequential small primes are run starting at 43. + * Is Fips 186.4 compliant if called with t as computed by + * mp_prime_rabin_miller_trials(); + * + * Sets result to 1 if probably prime, 0 otherwise + */ +int mp_prime_is_prime(const mp_int *a, int t, int *result); + +/* finds the next prime after the number "a" using "t" trials + * of Miller-Rabin. + * + * bbs_style = 1 means the prime must be congruent to 3 mod 4 + */ +int mp_prime_next_prime(mp_int *a, int t, int bbs_style); + +/* makes a truly random prime of a given size (bytes), + * call with bbs = 1 if you want it to be congruent to 3 mod 4 + * + * You have to supply a callback which fills in a buffer with random bytes. "dat" is a parameter you can + * have passed to the callback (e.g. a state or something). This function doesn't use "dat" itself + * so it can be NULL + * + * The prime generated will be larger than 2^(8*size). + */ +#define mp_prime_random(a, t, size, bbs, cb, dat) mp_prime_random_ex(a, t, ((size) * 8) + 1, (bbs==1)?LTM_PRIME_BBS:0, cb, dat) + +/* makes a truly random prime of a given size (bits), + * + * Flags are as follows: + * + * LTM_PRIME_BBS - make prime congruent to 3 mod 4 + * LTM_PRIME_SAFE - make sure (p-1)/2 is prime as well (implies LTM_PRIME_BBS) + * LTM_PRIME_2MSB_ON - make the 2nd highest bit one + * + * You have to supply a callback which fills in a buffer with random bytes. "dat" is a parameter you can + * have passed to the callback (e.g. a state or something). This function doesn't use "dat" itself + * so it can be NULL + * + */ +int mp_prime_random_ex(mp_int *a, int t, int size, int flags, ltm_prime_callback cb, void *dat); + +/* ---> radix conversion <--- */ +int mp_count_bits(const mp_int *a); + +int mp_unsigned_bin_size(const mp_int *a); +int mp_read_unsigned_bin(mp_int *a, const unsigned char *b, int c); +int mp_to_unsigned_bin(const mp_int *a, unsigned char *b); +int mp_to_unsigned_bin_n(const mp_int *a, unsigned char *b, unsigned long *outlen); + +int mp_signed_bin_size(const mp_int *a); +int mp_read_signed_bin(mp_int *a, const unsigned char *b, int c); +int mp_to_signed_bin(const mp_int *a, unsigned char *b); +int mp_to_signed_bin_n(const mp_int *a, unsigned char *b, unsigned long *outlen); + +int mp_read_radix(mp_int *a, const char *str, int radix); +int mp_toradix(const mp_int *a, char *str, int radix); +int mp_toradix_n(const mp_int *a, char *str, int radix, int maxlen); +int mp_radix_size(const mp_int *a, int radix, int *size); + +#ifndef LTM_NO_FILE +int mp_fread(mp_int *a, int radix, FILE *stream); +int mp_fwrite(const mp_int *a, int radix, FILE *stream); +#endif + +#define mp_read_raw(mp, str, len) mp_read_signed_bin((mp), (str), (len)) +#define mp_raw_size(mp) mp_signed_bin_size(mp) +#define mp_toraw(mp, str) mp_to_signed_bin((mp), (str)) +#define mp_read_mag(mp, str, len) mp_read_unsigned_bin((mp), (str), (len)) +#define mp_mag_size(mp) mp_unsigned_bin_size(mp) +#define mp_tomag(mp, str) mp_to_unsigned_bin((mp), (str)) + +#define mp_tobinary(M, S) mp_toradix((M), (S), 2) +#define mp_tooctal(M, S) mp_toradix((M), (S), 8) +#define mp_todecimal(M, S) mp_toradix((M), (S), 10) +#define mp_tohex(M, S) mp_toradix((M), (S), 16) + +#ifdef __cplusplus +} +#endif + +#endif + + +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/src/plugins/pro1_data_zip/ltc/headers/tommath_class.h b/src/plugins/pro1_data_zip/ltc/headers/tommath_class.h new file mode 100644 index 0000000..46f9996 --- /dev/null +++ b/src/plugins/pro1_data_zip/ltc/headers/tommath_class.h @@ -0,0 +1,1223 @@ +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * SPDX-License-Identifier: Unlicense + */ + +#if !(defined(LTM1) && defined(LTM2) && defined(LTM3)) +#if defined(LTM2) +# define LTM3 +#endif +#if defined(LTM1) +# define LTM2 +#endif +#define LTM1 +#if defined(LTM_ALL) +# define BN_ERROR_C +# define BN_FAST_MP_INVMOD_C +# define BN_FAST_MP_MONTGOMERY_REDUCE_C +# define BN_FAST_S_MP_MUL_DIGS_C +# define BN_FAST_S_MP_MUL_HIGH_DIGS_C +# define BN_FAST_S_MP_SQR_C +# define BN_MP_2EXPT_C +# define BN_MP_ABS_C +# define BN_MP_ADD_C +# define BN_MP_ADD_D_C +# define BN_MP_ADDMOD_C +# define BN_MP_AND_C +# define BN_MP_CLAMP_C +# define BN_MP_CLEAR_C +# define BN_MP_CLEAR_MULTI_C +# define BN_MP_CMP_C +# define BN_MP_CMP_D_C +# define BN_MP_CMP_MAG_C +# define BN_MP_CNT_LSB_C +# define BN_MP_COMPLEMENT_C +# define BN_MP_COPY_C +# define BN_MP_COUNT_BITS_C +# define BN_MP_DIV_C +# define BN_MP_DIV_2_C +# define BN_MP_DIV_2D_C +# define BN_MP_DIV_3_C +# define BN_MP_DIV_D_C +# define BN_MP_DR_IS_MODULUS_C +# define BN_MP_DR_REDUCE_C +# define BN_MP_DR_SETUP_C +# define BN_MP_EXCH_C +# define BN_MP_EXPORT_C +# define BN_MP_EXPT_D_C +# define BN_MP_EXPT_D_EX_C +# define BN_MP_EXPTMOD_C +# define BN_MP_EXPTMOD_FAST_C +# define BN_MP_EXTEUCLID_C +# define BN_MP_FREAD_C +# define BN_MP_FWRITE_C +# define BN_MP_GCD_C +# define BN_MP_GET_BIT_C +# define BN_MP_GET_DOUBLE_C +# define BN_MP_GET_INT_C +# define BN_MP_GET_LONG_C +# define BN_MP_GET_LONG_LONG_C +# define BN_MP_GROW_C +# define BN_MP_IMPORT_C +# define BN_MP_INIT_C +# define BN_MP_INIT_COPY_C +# define BN_MP_INIT_MULTI_C +# define BN_MP_INIT_SET_C +# define BN_MP_INIT_SET_INT_C +# define BN_MP_INIT_SIZE_C +# define BN_MP_INVMOD_C +# define BN_MP_INVMOD_SLOW_C +# define BN_MP_IS_SQUARE_C +# define BN_MP_JACOBI_C +# define BN_MP_KARATSUBA_MUL_C +# define BN_MP_KARATSUBA_SQR_C +# define BN_MP_KRONECKER_C +# define BN_MP_LCM_C +# define BN_MP_LSHD_C +# define BN_MP_MOD_C +# define BN_MP_MOD_2D_C +# define BN_MP_MOD_D_C +# define BN_MP_MONTGOMERY_CALC_NORMALIZATION_C +# define BN_MP_MONTGOMERY_REDUCE_C +# define BN_MP_MONTGOMERY_SETUP_C +# define BN_MP_MUL_C +# define BN_MP_MUL_2_C +# define BN_MP_MUL_2D_C +# define BN_MP_MUL_D_C +# define BN_MP_MULMOD_C +# define BN_MP_N_ROOT_C +# define BN_MP_N_ROOT_EX_C +# define BN_MP_NEG_C +# define BN_MP_OR_C +# define BN_MP_PRIME_FERMAT_C +# define BN_MP_PRIME_FROBENIUS_UNDERWOOD_C +# define BN_MP_PRIME_IS_DIVISIBLE_C +# define BN_MP_PRIME_IS_PRIME_C +# define BN_MP_PRIME_MILLER_RABIN_C +# define BN_MP_PRIME_NEXT_PRIME_C +# define BN_MP_PRIME_RABIN_MILLER_TRIALS_C +# define BN_MP_PRIME_RANDOM_EX_C +# define BN_MP_PRIME_STRONG_LUCAS_SELFRIDGE_C +# define BN_MP_RADIX_SIZE_C +# define BN_MP_RADIX_SMAP_C +# define BN_MP_RAND_C +# define BN_MP_READ_RADIX_C +# define BN_MP_READ_SIGNED_BIN_C +# define BN_MP_READ_UNSIGNED_BIN_C +# define BN_MP_REDUCE_C +# define BN_MP_REDUCE_2K_C +# define BN_MP_REDUCE_2K_L_C +# define BN_MP_REDUCE_2K_SETUP_C +# define BN_MP_REDUCE_2K_SETUP_L_C +# define BN_MP_REDUCE_IS_2K_C +# define BN_MP_REDUCE_IS_2K_L_C +# define BN_MP_REDUCE_SETUP_C +# define BN_MP_RSHD_C +# define BN_MP_SET_C +# define BN_MP_SET_DOUBLE_C +# define BN_MP_SET_INT_C +# define BN_MP_SET_LONG_C +# define BN_MP_SET_LONG_LONG_C +# define BN_MP_SHRINK_C +# define BN_MP_SIGNED_BIN_SIZE_C +# define BN_MP_SQR_C +# define BN_MP_SQRMOD_C +# define BN_MP_SQRT_C +# define BN_MP_SQRTMOD_PRIME_C +# define BN_MP_SUB_C +# define BN_MP_SUB_D_C +# define BN_MP_SUBMOD_C +# define BN_MP_TC_AND_C +# define BN_MP_TC_DIV_2D_C +# define BN_MP_TC_OR_C +# define BN_MP_TC_XOR_C +# define BN_MP_TO_SIGNED_BIN_C +# define BN_MP_TO_SIGNED_BIN_N_C +# define BN_MP_TO_UNSIGNED_BIN_C +# define BN_MP_TO_UNSIGNED_BIN_N_C +# define BN_MP_TOOM_MUL_C +# define BN_MP_TOOM_SQR_C +# define BN_MP_TORADIX_C +# define BN_MP_TORADIX_N_C +# define BN_MP_UNSIGNED_BIN_SIZE_C +# define BN_MP_XOR_C +# define BN_MP_ZERO_C +# define BN_PRIME_TAB_C +# define BN_REVERSE_C +# define BN_S_MP_ADD_C +# define BN_S_MP_EXPTMOD_C +# define BN_S_MP_MUL_DIGS_C +# define BN_S_MP_MUL_HIGH_DIGS_C +# define BN_S_MP_SQR_C +# define BN_S_MP_SUB_C +# define BNCORE_C +#endif +#if defined(BN_ERROR_C) +# define BN_MP_ERROR_TO_STRING_C +#endif + +#if defined(BN_FAST_MP_INVMOD_C) +# define BN_MP_ISEVEN_C +# define BN_MP_INIT_MULTI_C +# define BN_MP_COPY_C +# define BN_MP_MOD_C +# define BN_MP_ISZERO_C +# define BN_MP_SET_C +# define BN_MP_DIV_2_C +# define BN_MP_ISODD_C +# define BN_MP_SUB_C +# define BN_MP_CMP_C +# define BN_MP_CMP_D_C +# define BN_MP_ADD_C +# define BN_MP_CMP_MAG_C +# define BN_MP_EXCH_C +# define BN_MP_CLEAR_MULTI_C +#endif + +#if defined(BN_FAST_MP_MONTGOMERY_REDUCE_C) +# define BN_MP_GROW_C +# define BN_MP_RSHD_C +# define BN_MP_CLAMP_C +# define BN_MP_CMP_MAG_C +# define BN_S_MP_SUB_C +#endif + +#if defined(BN_FAST_S_MP_MUL_DIGS_C) +# define BN_MP_GROW_C +# define BN_MP_CLAMP_C +#endif + +#if defined(BN_FAST_S_MP_MUL_HIGH_DIGS_C) +# define BN_MP_GROW_C +# define BN_MP_CLAMP_C +#endif + +#if defined(BN_FAST_S_MP_SQR_C) +# define BN_MP_GROW_C +# define BN_MP_CLAMP_C +#endif + +#if defined(BN_MP_2EXPT_C) +# define BN_MP_ZERO_C +# define BN_MP_GROW_C +#endif + +#if defined(BN_MP_ABS_C) +# define BN_MP_COPY_C +#endif + +#if defined(BN_MP_ADD_C) +# define BN_S_MP_ADD_C +# define BN_MP_CMP_MAG_C +# define BN_S_MP_SUB_C +#endif + +#if defined(BN_MP_ADD_D_C) +# define BN_MP_GROW_C +# define BN_MP_SUB_D_C +# define BN_MP_CLAMP_C +#endif + +#if defined(BN_MP_ADDMOD_C) +# define BN_MP_INIT_C +# define BN_MP_ADD_C +# define BN_MP_CLEAR_C +# define BN_MP_MOD_C +#endif + +#if defined(BN_MP_AND_C) +# define BN_MP_INIT_COPY_C +# define BN_MP_CLAMP_C +# define BN_MP_EXCH_C +# define BN_MP_CLEAR_C +#endif + +#if defined(BN_MP_CLAMP_C) +#endif + +#if defined(BN_MP_CLEAR_C) +#endif + +#if defined(BN_MP_CLEAR_MULTI_C) +# define BN_MP_CLEAR_C +#endif + +#if defined(BN_MP_CMP_C) +# define BN_MP_CMP_MAG_C +#endif + +#if defined(BN_MP_CMP_D_C) +#endif + +#if defined(BN_MP_CMP_MAG_C) +#endif + +#if defined(BN_MP_CNT_LSB_C) +# define BN_MP_ISZERO_C +#endif + +#if defined(BN_MP_COMPLEMENT_C) +# define BN_MP_NEG_C +# define BN_MP_SUB_D_C +#endif + +#if defined(BN_MP_COPY_C) +# define BN_MP_GROW_C +#endif + +#if defined(BN_MP_COUNT_BITS_C) +#endif + +#if defined(BN_MP_DIV_C) +# define BN_MP_ISZERO_C +# define BN_MP_CMP_MAG_C +# define BN_MP_COPY_C +# define BN_MP_ZERO_C +# define BN_MP_INIT_MULTI_C +# define BN_MP_SET_C +# define BN_MP_COUNT_BITS_C +# define BN_MP_ABS_C +# define BN_MP_MUL_2D_C +# define BN_MP_CMP_C +# define BN_MP_SUB_C +# define BN_MP_ADD_C +# define BN_MP_DIV_2D_C +# define BN_MP_EXCH_C +# define BN_MP_CLEAR_MULTI_C +# define BN_MP_INIT_SIZE_C +# define BN_MP_INIT_C +# define BN_MP_INIT_COPY_C +# define BN_MP_LSHD_C +# define BN_MP_RSHD_C +# define BN_MP_MUL_D_C +# define BN_MP_CLAMP_C +# define BN_MP_CLEAR_C +#endif + +#if defined(BN_MP_DIV_2_C) +# define BN_MP_GROW_C +# define BN_MP_CLAMP_C +#endif + +#if defined(BN_MP_DIV_2D_C) +# define BN_MP_COPY_C +# define BN_MP_ZERO_C +# define BN_MP_MOD_2D_C +# define BN_MP_RSHD_C +# define BN_MP_CLAMP_C +#endif + +#if defined(BN_MP_DIV_3_C) +# define BN_MP_INIT_SIZE_C +# define BN_MP_CLAMP_C +# define BN_MP_EXCH_C +# define BN_MP_CLEAR_C +#endif + +#if defined(BN_MP_DIV_D_C) +# define BN_MP_ISZERO_C +# define BN_MP_COPY_C +# define BN_MP_DIV_2D_C +# define BN_MP_DIV_3_C +# define BN_MP_INIT_SIZE_C +# define BN_MP_CLAMP_C +# define BN_MP_EXCH_C +# define BN_MP_CLEAR_C +#endif + +#if defined(BN_MP_DR_IS_MODULUS_C) +#endif + +#if defined(BN_MP_DR_REDUCE_C) +# define BN_MP_GROW_C +# define BN_MP_CLAMP_C +# define BN_MP_CMP_MAG_C +# define BN_S_MP_SUB_C +#endif + +#if defined(BN_MP_DR_SETUP_C) +#endif + +#if defined(BN_MP_EXCH_C) +#endif + +#if defined(BN_MP_EXPORT_C) +# define BN_MP_INIT_COPY_C +# define BN_MP_COUNT_BITS_C +# define BN_MP_DIV_2D_C +# define BN_MP_CLEAR_C +#endif + +#if defined(BN_MP_EXPT_D_C) +# define BN_MP_EXPT_D_EX_C +#endif + +#if defined(BN_MP_EXPT_D_EX_C) +# define BN_MP_INIT_COPY_C +# define BN_MP_SET_C +# define BN_MP_MUL_C +# define BN_MP_CLEAR_C +# define BN_MP_SQR_C +#endif + +#if defined(BN_MP_EXPTMOD_C) +# define BN_MP_INIT_C +# define BN_MP_INVMOD_C +# define BN_MP_CLEAR_C +# define BN_MP_ABS_C +# define BN_MP_CLEAR_MULTI_C +# define BN_MP_REDUCE_IS_2K_L_C +# define BN_S_MP_EXPTMOD_C +# define BN_MP_DR_IS_MODULUS_C +# define BN_MP_REDUCE_IS_2K_C +# define BN_MP_ISODD_C +# define BN_MP_EXPTMOD_FAST_C +#endif + +#if defined(BN_MP_EXPTMOD_FAST_C) +# define BN_MP_COUNT_BITS_C +# define BN_MP_INIT_SIZE_C +# define BN_MP_CLEAR_C +# define BN_MP_MONTGOMERY_SETUP_C +# define BN_FAST_MP_MONTGOMERY_REDUCE_C +# define BN_MP_MONTGOMERY_REDUCE_C +# define BN_MP_DR_SETUP_C +# define BN_MP_DR_REDUCE_C +# define BN_MP_REDUCE_2K_SETUP_C +# define BN_MP_REDUCE_2K_C +# define BN_MP_MONTGOMERY_CALC_NORMALIZATION_C +# define BN_MP_MULMOD_C +# define BN_MP_SET_C +# define BN_MP_MOD_C +# define BN_MP_COPY_C +# define BN_MP_SQR_C +# define BN_MP_MUL_C +# define BN_MP_EXCH_C +#endif + +#if defined(BN_MP_EXTEUCLID_C) +# define BN_MP_INIT_MULTI_C +# define BN_MP_SET_C +# define BN_MP_COPY_C +# define BN_MP_ISZERO_C +# define BN_MP_DIV_C +# define BN_MP_MUL_C +# define BN_MP_SUB_C +# define BN_MP_NEG_C +# define BN_MP_EXCH_C +# define BN_MP_CLEAR_MULTI_C +#endif + +#if defined(BN_MP_FREAD_C) +# define BN_MP_ZERO_C +# define BN_MP_S_RMAP_REVERSE_SZ_C +# define BN_MP_S_RMAP_REVERSE_C +# define BN_MP_MUL_D_C +# define BN_MP_ADD_D_C +# define BN_MP_CMP_D_C +#endif + +#if defined(BN_MP_FWRITE_C) +# define BN_MP_RADIX_SIZE_C +# define BN_MP_TORADIX_C +#endif + +#if defined(BN_MP_GCD_C) +# define BN_MP_ISZERO_C +# define BN_MP_ABS_C +# define BN_MP_INIT_COPY_C +# define BN_MP_CNT_LSB_C +# define BN_MP_DIV_2D_C +# define BN_MP_CMP_MAG_C +# define BN_MP_EXCH_C +# define BN_S_MP_SUB_C +# define BN_MP_MUL_2D_C +# define BN_MP_CLEAR_C +#endif + +#if defined(BN_MP_GET_BIT_C) +# define BN_MP_ISZERO_C +#endif + +#if defined(BN_MP_GET_DOUBLE_C) +# define BN_MP_ISNEG_C +#endif + +#if defined(BN_MP_GET_INT_C) +#endif + +#if defined(BN_MP_GET_LONG_C) +#endif + +#if defined(BN_MP_GET_LONG_LONG_C) +#endif + +#if defined(BN_MP_GROW_C) +#endif + +#if defined(BN_MP_IMPORT_C) +# define BN_MP_ZERO_C +# define BN_MP_MUL_2D_C +# define BN_MP_CLAMP_C +#endif + +#if defined(BN_MP_INIT_C) +#endif + +#if defined(BN_MP_INIT_COPY_C) +# define BN_MP_INIT_SIZE_C +# define BN_MP_COPY_C +# define BN_MP_CLEAR_C +#endif + +#if defined(BN_MP_INIT_MULTI_C) +# define BN_MP_ERR_C +# define BN_MP_INIT_C +# define BN_MP_CLEAR_C +#endif + +#if defined(BN_MP_INIT_SET_C) +# define BN_MP_INIT_C +# define BN_MP_SET_C +#endif + +#if defined(BN_MP_INIT_SET_INT_C) +# define BN_MP_INIT_C +# define BN_MP_SET_INT_C +#endif + +#if defined(BN_MP_INIT_SIZE_C) +# define BN_MP_INIT_C +#endif + +#if defined(BN_MP_INVMOD_C) +# define BN_MP_CMP_D_C +# define BN_MP_ISODD_C +# define BN_FAST_MP_INVMOD_C +# define BN_MP_INVMOD_SLOW_C +#endif + +#if defined(BN_MP_INVMOD_SLOW_C) +# define BN_MP_ISZERO_C +# define BN_MP_INIT_MULTI_C +# define BN_MP_MOD_C +# define BN_MP_COPY_C +# define BN_MP_ISEVEN_C +# define BN_MP_SET_C +# define BN_MP_DIV_2_C +# define BN_MP_ISODD_C +# define BN_MP_ADD_C +# define BN_MP_SUB_C +# define BN_MP_CMP_C +# define BN_MP_CMP_D_C +# define BN_MP_CMP_MAG_C +# define BN_MP_EXCH_C +# define BN_MP_CLEAR_MULTI_C +#endif + +#if defined(BN_MP_IS_SQUARE_C) +# define BN_MP_MOD_D_C +# define BN_MP_INIT_SET_INT_C +# define BN_MP_MOD_C +# define BN_MP_GET_INT_C +# define BN_MP_SQRT_C +# define BN_MP_SQR_C +# define BN_MP_CMP_MAG_C +# define BN_MP_CLEAR_C +#endif + +#if defined(BN_MP_JACOBI_C) +# define BN_MP_KRONECKER_C +# define BN_MP_ISNEG_C +# define BN_MP_CMP_D_C +#endif + +#if defined(BN_MP_KARATSUBA_MUL_C) +# define BN_MP_MUL_C +# define BN_MP_INIT_SIZE_C +# define BN_MP_CLAMP_C +# define BN_S_MP_ADD_C +# define BN_MP_ADD_C +# define BN_S_MP_SUB_C +# define BN_MP_LSHD_C +# define BN_MP_CLEAR_C +#endif + +#if defined(BN_MP_KARATSUBA_SQR_C) +# define BN_MP_INIT_SIZE_C +# define BN_MP_CLAMP_C +# define BN_MP_SQR_C +# define BN_S_MP_ADD_C +# define BN_S_MP_SUB_C +# define BN_MP_LSHD_C +# define BN_MP_ADD_C +# define BN_MP_CLEAR_C +#endif + +#if defined(BN_MP_KRONECKER_C) +# define BN_MP_ISZERO_C +# define BN_MP_ISEVEN_C +# define BN_MP_INIT_COPY_C +# define BN_MP_CNT_LSB_C +# define BN_MP_DIV_2D_C +# define BN_MP_CMP_D_C +# define BN_MP_COPY_C +# define BN_MP_MOD_C +# define BN_MP_CLEAR_C +#endif + +#if defined(BN_MP_LCM_C) +# define BN_MP_INIT_MULTI_C +# define BN_MP_GCD_C +# define BN_MP_CMP_MAG_C +# define BN_MP_DIV_C +# define BN_MP_MUL_C +# define BN_MP_CLEAR_MULTI_C +#endif + +#if defined(BN_MP_LSHD_C) +# define BN_MP_ISZERO_C +# define BN_MP_GROW_C +# define BN_MP_RSHD_C +#endif + +#if defined(BN_MP_MOD_C) +# define BN_MP_INIT_SIZE_C +# define BN_MP_DIV_C +# define BN_MP_CLEAR_C +# define BN_MP_ISZERO_C +# define BN_MP_EXCH_C +# define BN_MP_ADD_C +#endif + +#if defined(BN_MP_MOD_2D_C) +# define BN_MP_ZERO_C +# define BN_MP_COPY_C +# define BN_MP_CLAMP_C +#endif + +#if defined(BN_MP_MOD_D_C) +# define BN_MP_DIV_D_C +#endif + +#if defined(BN_MP_MONTGOMERY_CALC_NORMALIZATION_C) +# define BN_MP_COUNT_BITS_C +# define BN_MP_2EXPT_C +# define BN_MP_SET_C +# define BN_MP_MUL_2_C +# define BN_MP_CMP_MAG_C +# define BN_S_MP_SUB_C +#endif + +#if defined(BN_MP_MONTGOMERY_REDUCE_C) +# define BN_FAST_MP_MONTGOMERY_REDUCE_C +# define BN_MP_GROW_C +# define BN_MP_CLAMP_C +# define BN_MP_RSHD_C +# define BN_MP_CMP_MAG_C +# define BN_S_MP_SUB_C +#endif + +#if defined(BN_MP_MONTGOMERY_SETUP_C) +#endif + +#if defined(BN_MP_MUL_C) +# define BN_MP_TOOM_MUL_C +# define BN_MP_KARATSUBA_MUL_C +# define BN_FAST_S_MP_MUL_DIGS_C +# define BN_S_MP_MUL_C +# define BN_S_MP_MUL_DIGS_C +#endif + +#if defined(BN_MP_MUL_2_C) +# define BN_MP_GROW_C +#endif + +#if defined(BN_MP_MUL_2D_C) +# define BN_MP_COPY_C +# define BN_MP_GROW_C +# define BN_MP_LSHD_C +# define BN_MP_CLAMP_C +#endif + +#if defined(BN_MP_MUL_D_C) +# define BN_MP_GROW_C +# define BN_MP_CLAMP_C +#endif + +#if defined(BN_MP_MULMOD_C) +# define BN_MP_INIT_SIZE_C +# define BN_MP_MUL_C +# define BN_MP_CLEAR_C +# define BN_MP_MOD_C +#endif + +#if defined(BN_MP_N_ROOT_C) +# define BN_MP_N_ROOT_EX_C +#endif + +#if defined(BN_MP_N_ROOT_EX_C) +# define BN_MP_INIT_C +# define BN_MP_SET_C +# define BN_MP_COPY_C +# define BN_MP_EXPT_D_EX_C +# define BN_MP_MUL_C +# define BN_MP_SUB_C +# define BN_MP_MUL_D_C +# define BN_MP_DIV_C +# define BN_MP_CMP_C +# define BN_MP_SUB_D_C +# define BN_MP_EXCH_C +# define BN_MP_CLEAR_C +#endif + +#if defined(BN_MP_NEG_C) +# define BN_MP_COPY_C +# define BN_MP_ISZERO_C +#endif + +#if defined(BN_MP_OR_C) +# define BN_MP_INIT_COPY_C +# define BN_MP_CLAMP_C +# define BN_MP_EXCH_C +# define BN_MP_CLEAR_C +#endif + +#if defined(BN_MP_PRIME_FERMAT_C) +# define BN_MP_CMP_D_C +# define BN_MP_INIT_C +# define BN_MP_EXPTMOD_C +# define BN_MP_CMP_C +# define BN_MP_CLEAR_C +#endif + +#if defined(BN_MP_PRIME_FROBENIUS_UNDERWOOD_C) +# define BN_MP_PRIME_IS_PRIME_C +# define BN_MP_INIT_MULTI_C +# define BN_MP_SET_LONG_C +# define BN_MP_SQR_C +# define BN_MP_SUB_D_C +# define BN_MP_KRONECKER_C +# define BN_MP_GCD_C +# define BN_MP_ADD_D_C +# define BN_MP_SET_C +# define BN_MP_COUNT_BITS_C +# define BN_MP_MUL_2_C +# define BN_MP_MUL_D_C +# define BN_MP_ADD_C +# define BN_MP_MUL_C +# define BN_MP_SUB_C +# define BN_MP_MOD_C +# define BN_MP_GET_BIT_C +# define BN_MP_EXCH_C +# define BN_MP_ISZERO_C +# define BN_MP_CMP_C +# define BN_MP_CLEAR_MULTI_C +#endif + +#if defined(BN_MP_PRIME_IS_DIVISIBLE_C) +# define BN_MP_MOD_D_C +#endif + +#if defined(BN_MP_PRIME_IS_PRIME_C) +# define BN_MP_ISEVEN_C +# define BN_MP_IS_SQUARE_C +# define BN_MP_CMP_D_C +# define BN_MP_PRIME_IS_DIVISIBLE_C +# define BN_MP_INIT_SET_C +# define BN_MP_PRIME_MILLER_RABIN_C +# define BN_MP_PRIME_FROBENIUS_UNDERWOOD_C +# define BN_MP_PRIME_STRONG_LUCAS_SELFRIDGE_C +# define BN_MP_READ_RADIX_C +# define BN_MP_CMP_C +# define BN_MP_SET_C +# define BN_MP_COUNT_BITS_C +# define BN_MP_RAND_C +# define BN_MP_DIV_2D_C +# define BN_MP_CLEAR_C +#endif + +#if defined(BN_MP_PRIME_MILLER_RABIN_C) +# define BN_MP_CMP_D_C +# define BN_MP_INIT_COPY_C +# define BN_MP_SUB_D_C +# define BN_MP_CNT_LSB_C +# define BN_MP_DIV_2D_C +# define BN_MP_EXPTMOD_C +# define BN_MP_CMP_C +# define BN_MP_SQRMOD_C +# define BN_MP_CLEAR_C +#endif + +#if defined(BN_MP_PRIME_NEXT_PRIME_C) +# define BN_MP_CMP_D_C +# define BN_MP_SET_C +# define BN_MP_SUB_D_C +# define BN_MP_ISEVEN_C +# define BN_MP_MOD_D_C +# define BN_MP_INIT_C +# define BN_MP_ADD_D_C +# define BN_MP_PRIME_IS_PRIME_C +# define BN_MP_CLEAR_C +#endif + +#if defined(BN_MP_PRIME_RABIN_MILLER_TRIALS_C) +#endif + +#if defined(BN_MP_PRIME_RANDOM_EX_C) +# define BN_MP_READ_UNSIGNED_BIN_C +# define BN_MP_PRIME_IS_PRIME_C +# define BN_MP_SUB_D_C +# define BN_MP_DIV_2_C +# define BN_MP_MUL_2_C +# define BN_MP_ADD_D_C +#endif + +#if defined(BN_MP_PRIME_STRONG_LUCAS_SELFRIDGE_C) +# define BN_MP_PRIME_IS_PRIME_C +# define BN_MP_MUL_D_C +# define BN_S_MP_MUL_SI_C +# define BN_MP_INIT_C +# define BN_MP_SET_LONG_C +# define BN_MP_MUL_C +# define BN_MP_CLEAR_C +# define BN_MP_INIT_MULTI_C +# define BN_MP_GCD_C +# define BN_MP_CMP_D_C +# define BN_MP_CMP_C +# define BN_MP_KRONECKER_C +# define BN_MP_ADD_D_C +# define BN_MP_CNT_LSB_C +# define BN_MP_DIV_2D_C +# define BN_MP_SET_C +# define BN_MP_MUL_2_C +# define BN_MP_COUNT_BITS_C +# define BN_MP_MOD_C +# define BN_MP_SQR_C +# define BN_MP_SUB_C +# define BN_MP_GET_BIT_C +# define BN_MP_ADD_C +# define BN_MP_ISODD_C +# define BN_MP_DIV_2_C +# define BN_MP_SUB_D_C +# define BN_MP_ISZERO_C +# define BN_MP_CLEAR_MULTI_C +#endif + +#if defined(BN_MP_RADIX_SIZE_C) +# define BN_MP_ISZERO_C +# define BN_MP_COUNT_BITS_C +# define BN_MP_INIT_COPY_C +# define BN_MP_DIV_D_C +# define BN_MP_CLEAR_C +#endif + +#if defined(BN_MP_RADIX_SMAP_C) +# define BN_MP_S_RMAP_C +# define BN_MP_S_RMAP_REVERSE_C +# define BN_MP_S_RMAP_REVERSE_SZ_C +#endif + +#if defined(BN_MP_RAND_C) +# define BN_MP_RAND_DIGIT_C +# define BN_MP_ZERO_C +# define BN_MP_ADD_D_C +# define BN_MP_LSHD_C +#endif + +#if defined(BN_MP_READ_RADIX_C) +# define BN_MP_ZERO_C +# define BN_MP_S_RMAP_REVERSE_SZ_C +# define BN_MP_S_RMAP_REVERSE_C +# define BN_MP_MUL_D_C +# define BN_MP_ADD_D_C +# define BN_MP_ISZERO_C +#endif + +#if defined(BN_MP_READ_SIGNED_BIN_C) +# define BN_MP_READ_UNSIGNED_BIN_C +#endif + +#if defined(BN_MP_READ_UNSIGNED_BIN_C) +# define BN_MP_GROW_C +# define BN_MP_ZERO_C +# define BN_MP_MUL_2D_C +# define BN_MP_CLAMP_C +#endif + +#if defined(BN_MP_REDUCE_C) +# define BN_MP_REDUCE_SETUP_C +# define BN_MP_INIT_COPY_C +# define BN_MP_RSHD_C +# define BN_MP_MUL_C +# define BN_S_MP_MUL_HIGH_DIGS_C +# define BN_FAST_S_MP_MUL_HIGH_DIGS_C +# define BN_MP_MOD_2D_C +# define BN_S_MP_MUL_DIGS_C +# define BN_MP_SUB_C +# define BN_MP_CMP_D_C +# define BN_MP_SET_C +# define BN_MP_LSHD_C +# define BN_MP_ADD_C +# define BN_MP_CMP_C +# define BN_S_MP_SUB_C +# define BN_MP_CLEAR_C +#endif + +#if defined(BN_MP_REDUCE_2K_C) +# define BN_MP_INIT_C +# define BN_MP_COUNT_BITS_C +# define BN_MP_DIV_2D_C +# define BN_MP_MUL_D_C +# define BN_S_MP_ADD_C +# define BN_MP_CMP_MAG_C +# define BN_S_MP_SUB_C +# define BN_MP_CLEAR_C +#endif + +#if defined(BN_MP_REDUCE_2K_L_C) +# define BN_MP_INIT_C +# define BN_MP_COUNT_BITS_C +# define BN_MP_DIV_2D_C +# define BN_MP_MUL_C +# define BN_S_MP_ADD_C +# define BN_MP_CMP_MAG_C +# define BN_S_MP_SUB_C +# define BN_MP_CLEAR_C +#endif + +#if defined(BN_MP_REDUCE_2K_SETUP_C) +# define BN_MP_INIT_C +# define BN_MP_COUNT_BITS_C +# define BN_MP_2EXPT_C +# define BN_MP_CLEAR_C +# define BN_S_MP_SUB_C +#endif + +#if defined(BN_MP_REDUCE_2K_SETUP_L_C) +# define BN_MP_INIT_C +# define BN_MP_2EXPT_C +# define BN_MP_COUNT_BITS_C +# define BN_S_MP_SUB_C +# define BN_MP_CLEAR_C +#endif + +#if defined(BN_MP_REDUCE_IS_2K_C) +# define BN_MP_REDUCE_2K_C +# define BN_MP_COUNT_BITS_C +#endif + +#if defined(BN_MP_REDUCE_IS_2K_L_C) +#endif + +#if defined(BN_MP_REDUCE_SETUP_C) +# define BN_MP_2EXPT_C +# define BN_MP_DIV_C +#endif + +#if defined(BN_MP_RSHD_C) +# define BN_MP_ZERO_C +#endif + +#if defined(BN_MP_SET_C) +# define BN_MP_ZERO_C +#endif + +#if defined(BN_MP_SET_DOUBLE_C) +# define BN_MP_SET_LONG_LONG_C +# define BN_MP_DIV_2D_C +# define BN_MP_MUL_2D_C +# define BN_MP_ISZERO_C +#endif + +#if defined(BN_MP_SET_INT_C) +# define BN_MP_ZERO_C +# define BN_MP_MUL_2D_C +# define BN_MP_CLAMP_C +#endif + +#if defined(BN_MP_SET_LONG_C) +#endif + +#if defined(BN_MP_SET_LONG_LONG_C) +#endif + +#if defined(BN_MP_SHRINK_C) +#endif + +#if defined(BN_MP_SIGNED_BIN_SIZE_C) +# define BN_MP_UNSIGNED_BIN_SIZE_C +#endif + +#if defined(BN_MP_SQR_C) +# define BN_MP_TOOM_SQR_C +# define BN_MP_KARATSUBA_SQR_C +# define BN_FAST_S_MP_SQR_C +# define BN_S_MP_SQR_C +#endif + +#if defined(BN_MP_SQRMOD_C) +# define BN_MP_INIT_C +# define BN_MP_SQR_C +# define BN_MP_CLEAR_C +# define BN_MP_MOD_C +#endif + +#if defined(BN_MP_SQRT_C) +# define BN_MP_N_ROOT_C +# define BN_MP_ISZERO_C +# define BN_MP_ZERO_C +# define BN_MP_INIT_COPY_C +# define BN_MP_RSHD_C +# define BN_MP_DIV_C +# define BN_MP_ADD_C +# define BN_MP_DIV_2_C +# define BN_MP_CMP_MAG_C +# define BN_MP_EXCH_C +# define BN_MP_CLEAR_C +#endif + +#if defined(BN_MP_SQRTMOD_PRIME_C) +# define BN_MP_CMP_D_C +# define BN_MP_ZERO_C +# define BN_MP_JACOBI_C +# define BN_MP_INIT_MULTI_C +# define BN_MP_MOD_D_C +# define BN_MP_ADD_D_C +# define BN_MP_DIV_2_C +# define BN_MP_EXPTMOD_C +# define BN_MP_COPY_C +# define BN_MP_SUB_D_C +# define BN_MP_ISEVEN_C +# define BN_MP_SET_INT_C +# define BN_MP_SQRMOD_C +# define BN_MP_MULMOD_C +# define BN_MP_SET_C +# define BN_MP_CLEAR_MULTI_C +#endif + +#if defined(BN_MP_SUB_C) +# define BN_S_MP_ADD_C +# define BN_MP_CMP_MAG_C +# define BN_S_MP_SUB_C +#endif + +#if defined(BN_MP_SUB_D_C) +# define BN_MP_GROW_C +# define BN_MP_ADD_D_C +# define BN_MP_CLAMP_C +#endif + +#if defined(BN_MP_SUBMOD_C) +# define BN_MP_INIT_C +# define BN_MP_SUB_C +# define BN_MP_CLEAR_C +# define BN_MP_MOD_C +#endif + +#if defined(BN_MP_TC_AND_C) +# define BN_MP_ISNEG_C +# define BN_MP_COUNT_BITS_C +# define BN_MP_INIT_SET_INT_C +# define BN_MP_MUL_2D_C +# define BN_MP_INIT_C +# define BN_MP_ADD_C +# define BN_MP_CLEAR_C +# define BN_MP_AND_C +# define BN_MP_SUB_C +#endif + +#if defined(BN_MP_TC_DIV_2D_C) +# define BN_MP_ISNEG_C +# define BN_MP_DIV_2D_C +# define BN_MP_ADD_D_C +# define BN_MP_SUB_D_C +#endif + +#if defined(BN_MP_TC_OR_C) +# define BN_MP_ISNEG_C +# define BN_MP_COUNT_BITS_C +# define BN_MP_INIT_SET_INT_C +# define BN_MP_MUL_2D_C +# define BN_MP_INIT_C +# define BN_MP_ADD_C +# define BN_MP_CLEAR_C +# define BN_MP_OR_C +# define BN_MP_SUB_C +#endif + +#if defined(BN_MP_TC_XOR_C) +# define BN_MP_ISNEG_C +# define BN_MP_COUNT_BITS_C +# define BN_MP_INIT_SET_INT_C +# define BN_MP_MUL_2D_C +# define BN_MP_INIT_C +# define BN_MP_ADD_C +# define BN_MP_CLEAR_C +# define BN_MP_XOR_C +# define BN_MP_SUB_C +#endif + +#if defined(BN_MP_TO_SIGNED_BIN_C) +# define BN_MP_TO_UNSIGNED_BIN_C +#endif + +#if defined(BN_MP_TO_SIGNED_BIN_N_C) +# define BN_MP_SIGNED_BIN_SIZE_C +# define BN_MP_TO_SIGNED_BIN_C +#endif + +#if defined(BN_MP_TO_UNSIGNED_BIN_C) +# define BN_MP_INIT_COPY_C +# define BN_MP_ISZERO_C +# define BN_MP_DIV_2D_C +# define BN_MP_CLEAR_C +#endif + +#if defined(BN_MP_TO_UNSIGNED_BIN_N_C) +# define BN_MP_UNSIGNED_BIN_SIZE_C +# define BN_MP_TO_UNSIGNED_BIN_C +#endif + +#if defined(BN_MP_TOOM_MUL_C) +# define BN_MP_INIT_MULTI_C +# define BN_MP_MOD_2D_C +# define BN_MP_COPY_C +# define BN_MP_RSHD_C +# define BN_MP_MUL_C +# define BN_MP_MUL_2_C +# define BN_MP_ADD_C +# define BN_MP_SUB_C +# define BN_MP_DIV_2_C +# define BN_MP_MUL_2D_C +# define BN_MP_MUL_D_C +# define BN_MP_DIV_3_C +# define BN_MP_LSHD_C +# define BN_MP_CLEAR_MULTI_C +#endif + +#if defined(BN_MP_TOOM_SQR_C) +# define BN_MP_INIT_MULTI_C +# define BN_MP_MOD_2D_C +# define BN_MP_COPY_C +# define BN_MP_RSHD_C +# define BN_MP_SQR_C +# define BN_MP_MUL_2_C +# define BN_MP_ADD_C +# define BN_MP_SUB_C +# define BN_MP_DIV_2_C +# define BN_MP_MUL_2D_C +# define BN_MP_MUL_D_C +# define BN_MP_DIV_3_C +# define BN_MP_LSHD_C +# define BN_MP_CLEAR_MULTI_C +#endif + +#if defined(BN_MP_TORADIX_C) +# define BN_MP_ISZERO_C +# define BN_MP_INIT_COPY_C +# define BN_MP_DIV_D_C +# define BN_MP_CLEAR_C +# define BN_MP_S_RMAP_C +#endif + +#if defined(BN_MP_TORADIX_N_C) +# define BN_MP_ISZERO_C +# define BN_MP_INIT_COPY_C +# define BN_MP_DIV_D_C +# define BN_MP_CLEAR_C +# define BN_MP_S_RMAP_C +#endif + +#if defined(BN_MP_UNSIGNED_BIN_SIZE_C) +# define BN_MP_COUNT_BITS_C +#endif + +#if defined(BN_MP_XOR_C) +# define BN_MP_INIT_COPY_C +# define BN_MP_CLAMP_C +# define BN_MP_EXCH_C +# define BN_MP_CLEAR_C +#endif + +#if defined(BN_MP_ZERO_C) +#endif + +#if defined(BN_PRIME_TAB_C) +#endif + +#if defined(BN_REVERSE_C) +#endif + +#if defined(BN_S_MP_ADD_C) +# define BN_MP_GROW_C +# define BN_MP_CLAMP_C +#endif + +#if defined(BN_S_MP_EXPTMOD_C) +# define BN_MP_COUNT_BITS_C +# define BN_MP_INIT_C +# define BN_MP_CLEAR_C +# define BN_MP_REDUCE_SETUP_C +# define BN_MP_REDUCE_C +# define BN_MP_REDUCE_2K_SETUP_L_C +# define BN_MP_REDUCE_2K_L_C +# define BN_MP_MOD_C +# define BN_MP_COPY_C +# define BN_MP_SQR_C +# define BN_MP_MUL_C +# define BN_MP_SET_C +# define BN_MP_EXCH_C +#endif + +#if defined(BN_S_MP_MUL_DIGS_C) +# define BN_FAST_S_MP_MUL_DIGS_C +# define BN_MP_INIT_SIZE_C +# define BN_MP_CLAMP_C +# define BN_MP_EXCH_C +# define BN_MP_CLEAR_C +#endif + +#if defined(BN_S_MP_MUL_HIGH_DIGS_C) +# define BN_FAST_S_MP_MUL_HIGH_DIGS_C +# define BN_MP_INIT_SIZE_C +# define BN_MP_CLAMP_C +# define BN_MP_EXCH_C +# define BN_MP_CLEAR_C +#endif + +#if defined(BN_S_MP_SQR_C) +# define BN_MP_INIT_SIZE_C +# define BN_MP_CLAMP_C +# define BN_MP_EXCH_C +# define BN_MP_CLEAR_C +#endif + +#if defined(BN_S_MP_SUB_C) +# define BN_MP_GROW_C +# define BN_MP_CLAMP_C +#endif + +#if defined(BNCORE_C) +#endif + +#ifdef LTM3 +# define LTM_LAST +#endif + +#include +#include +#else +# define LTM_LAST +#endif + +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/src/plugins/pro1_data_zip/ltc/headers/tommath_superclass.h b/src/plugins/pro1_data_zip/ltc/headers/tommath_superclass.h new file mode 100644 index 0000000..7b98ed6 --- /dev/null +++ b/src/plugins/pro1_data_zip/ltc/headers/tommath_superclass.h @@ -0,0 +1,88 @@ +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * SPDX-License-Identifier: Unlicense + */ + +/* super class file for PK algos */ + +/* default ... include all MPI */ +#define LTM_ALL + +/* RSA only (does not support DH/DSA/ECC) */ +/* #define SC_RSA_1 */ + +/* For reference.... On an Athlon64 optimizing for speed... + + LTM's mpi.o with all functions [striped] is 142KiB in size. + +*/ + +/* Works for RSA only, mpi.o is 68KiB */ +#ifdef SC_RSA_1 +# define BN_MP_SHRINK_C +# define BN_MP_LCM_C +# define BN_MP_PRIME_RANDOM_EX_C +# define BN_MP_INVMOD_C +# define BN_MP_GCD_C +# define BN_MP_MOD_C +# define BN_MP_MULMOD_C +# define BN_MP_ADDMOD_C +# define BN_MP_EXPTMOD_C +# define BN_MP_SET_INT_C +# define BN_MP_INIT_MULTI_C +# define BN_MP_CLEAR_MULTI_C +# define BN_MP_UNSIGNED_BIN_SIZE_C +# define BN_MP_TO_UNSIGNED_BIN_C +# define BN_MP_MOD_D_C +# define BN_MP_PRIME_RABIN_MILLER_TRIALS_C +# define BN_REVERSE_C +# define BN_PRIME_TAB_C + +/* other modifiers */ +# define BN_MP_DIV_SMALL /* Slower division, not critical */ + +/* here we are on the last pass so we turn things off. The functions classes are still there + * but we remove them specifically from the build. This also invokes tweaks in functions + * like removing support for even moduli, etc... + */ +# ifdef LTM_LAST +# undef BN_MP_TOOM_MUL_C +# undef BN_MP_TOOM_SQR_C +# undef BN_MP_KARATSUBA_MUL_C +# undef BN_MP_KARATSUBA_SQR_C +# undef BN_MP_REDUCE_C +# undef BN_MP_REDUCE_SETUP_C +# undef BN_MP_DR_IS_MODULUS_C +# undef BN_MP_DR_SETUP_C +# undef BN_MP_DR_REDUCE_C +# undef BN_MP_REDUCE_IS_2K_C +# undef BN_MP_REDUCE_2K_SETUP_C +# undef BN_MP_REDUCE_2K_C +# undef BN_S_MP_EXPTMOD_C +# undef BN_MP_DIV_3_C +# undef BN_S_MP_MUL_HIGH_DIGS_C +# undef BN_FAST_S_MP_MUL_HIGH_DIGS_C +# undef BN_FAST_MP_INVMOD_C + +/* To safely undefine these you have to make sure your RSA key won't exceed the Comba threshold + * which is roughly 255 digits [7140 bits for 32-bit machines, 15300 bits for 64-bit machines] + * which means roughly speaking you can handle upto 2536-bit RSA keys with these defined without + * trouble. + */ +# undef BN_S_MP_MUL_DIGS_C +# undef BN_S_MP_SQR_C +# undef BN_MP_MONTGOMERY_REDUCE_C +# endif + +#endif + +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/src/plugins/pro1_data_zip/ltc/linux_x86/libtomcrypt.a b/src/plugins/pro1_data_zip/ltc/linux_x86/libtomcrypt.a new file mode 100644 index 0000000..b358e3b Binary files /dev/null and b/src/plugins/pro1_data_zip/ltc/linux_x86/libtomcrypt.a differ diff --git a/src/plugins/pro1_data_zip/ltc/linux_x86/libtomcrypt_debug.a b/src/plugins/pro1_data_zip/ltc/linux_x86/libtomcrypt_debug.a new file mode 100644 index 0000000..ebe0c9a Binary files /dev/null and b/src/plugins/pro1_data_zip/ltc/linux_x86/libtomcrypt_debug.a differ diff --git a/src/plugins/pro1_data_zip/ltc/linux_x86/libtommath.a b/src/plugins/pro1_data_zip/ltc/linux_x86/libtommath.a new file mode 100644 index 0000000..27acef7 Binary files /dev/null and b/src/plugins/pro1_data_zip/ltc/linux_x86/libtommath.a differ diff --git a/src/plugins/pro1_data_zip/ow/crcutil.c b/src/plugins/pro1_data_zip/ow/crcutil.c new file mode 100644 index 0000000..4d67996 --- /dev/null +++ b/src/plugins/pro1_data_zip/ow/crcutil.c @@ -0,0 +1,120 @@ +/*--------------------------------------------------------------------------- + * Copyright (C) 2000 Dallas Semiconductor Corporation, All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL DALLAS SEMICONDUCTOR BE LIABLE FOR ANY CLAIM, DAMAGES + * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of Dallas Semiconductor + * shall not be used except as stated in the Dallas Semiconductor + * Branding Policy. + *-------------------------------------------------------------------------- + * + * crcutil.c - Keeps track of the CRC for 16 and 8 bit operations + * version 2.00 + */ + +/* Include files */ +#include "ownet.h" + +/* Local global variables */ +ushort utilcrc16[MAX_PORTNUM]; +uchar utilcrc8[MAX_PORTNUM]; +static short oddparity[16] = { 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0 }; +static uchar dscrc_table[] = { + 0, 94,188,226, 97, 63,221,131,194,156,126, 32,163,253, 31, 65, + 157,195, 33,127,252,162, 64, 30, 95, 1,227,189, 62, 96,130,220, + 35,125,159,193, 66, 28,254,160,225,191, 93, 3,128,222, 60, 98, + 190,224, 2, 92,223,129, 99, 61,124, 34,192,158, 29, 67,161,255, + 70, 24,250,164, 39,121,155,197,132,218, 56,102,229,187, 89, 7, + 219,133,103, 57,186,228, 6, 88, 25, 71,165,251,120, 38,196,154, + 101, 59,217,135, 4, 90,184,230,167,249, 27, 69,198,152,122, 36, + 248,166, 68, 26,153,199, 37,123, 58,100,134,216, 91, 5,231,185, + 140,210, 48,110,237,179, 81, 15, 78, 16,242,172, 47,113,147,205, + 17, 79,173,243,112, 46,204,146,211,141,111, 49,178,236, 14, 80, + 175,241, 19, 77,206,144,114, 44,109, 51,209,143, 12, 82,176,238, + 50,108,142,208, 83, 13,239,177,240,174, 76, 18,145,207, 45,115, + 202,148,118, 40,171,245, 23, 73, 8, 86,180,234,105, 55,213,139, + 87, 9,235,181, 54,104,138,212,149,203, 41,119,244,170, 72, 22, + 233,183, 85, 11,136,214, 52,106, 43,117,151,201, 74, 20,246,168, + 116, 42,200,150, 21, 75,169,247,182,232, 10, 84,215,137,107, 53}; + +/*-------------------------------------------------------------------------- + * Reset crc16 to the value passed in + * + * 'reset' - data to set crc16 to. + */ +void setcrc16(int portnum, ushort reset) +{ + utilcrc16[portnum&0x0FF] = reset; + return; +} + +/*-------------------------------------------------------------------------- + * Reset crc8 to the value passed in + * + * 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to + * indicate the symbolic port number. + * 'reset' - data to set crc8 to + */ +void setcrc8(int portnum, uchar reset) +{ + utilcrc8[portnum&0x0FF] = reset; + return; +} + +/*-------------------------------------------------------------------------- + * Calculate a new CRC16 from the input data short. Return the current + * CRC16 and also update the global variable CRC16. + * + * 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to + * indicate the symbolic port number. + * 'data' - data to perform a CRC16 on + * + * Returns: the current CRC16 + */ +ushort docrc16(int portnum, ushort cdata) +{ + cdata = (cdata ^ (utilcrc16[portnum&0x0FF] & 0xff)) & 0xff; + utilcrc16[portnum&0x0FF] >>= 8; + + if (oddparity[cdata & 0xf] ^ oddparity[cdata >> 4]) + utilcrc16[portnum&0x0FF] ^= 0xc001; + + cdata <<= 6; + utilcrc16[portnum&0x0FF] ^= cdata; + cdata <<= 1; + utilcrc16[portnum&0x0FF] ^= cdata; + + return utilcrc16[portnum&0x0FF]; +} + +/*-------------------------------------------------------------------------- + * Update the Dallas Semiconductor One Wire CRC (utilcrc8) from the global + * variable utilcrc8 and the argument. + * + * 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to + * indicate the symbolic port number. + * 'x' - data byte to calculate the 8 bit crc from + * + * Returns: the updated utilcrc8. + */ +uchar docrc8(int portnum, uchar x) +{ + utilcrc8[portnum&0x0FF] = dscrc_table[utilcrc8[portnum&0x0FF] ^ x]; + return utilcrc8[portnum&0x0FF]; +} diff --git a/src/plugins/pro1_data_zip/ow/ds2480.h b/src/plugins/pro1_data_zip/ow/ds2480.h new file mode 100644 index 0000000..915d027 --- /dev/null +++ b/src/plugins/pro1_data_zip/ow/ds2480.h @@ -0,0 +1,206 @@ +//--------------------------------------------------------------------------- +// Copyright (C) 2000 Dallas Semiconductor Corporation, All Rights Reserved. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL DALLAS SEMICONDUCTOR BE LIABLE FOR ANY CLAIM, DAMAGES +// OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// +// Except as contained in this notice, the name of Dallas Semiconductor +// shall not be used except as stated in the Dallas Semiconductor +// Branding Policy. +//--------------------------------------------------------------------------- +// +// DS2480.H - This file contains the DS2480B constants +// +// Version: 2.00 +// +// History: 1.02 -> 1.03 Make sure uchar is not defined twice. +// +// + +#include "ownet.h" + +#ifndef __MC68K__ +#include +#ifndef _WIN32_WCE +#include +#endif +#endif + +// Mode Commands +#define MODE_DATA 0xE1 +#define MODE_COMMAND 0xE3 +#define MODE_STOP_PULSE 0xF1 + +// Return byte value +#define RB_CHIPID_MASK 0x1C +#define RB_RESET_MASK 0x03 +#define RB_1WIRESHORT 0x00 +#define RB_PRESENCE 0x01 +#define RB_ALARMPRESENCE 0x02 +#define RB_NOPRESENCE 0x03 + +#define RB_BIT_MASK 0x03 +#define RB_BIT_ONE 0x03 +#define RB_BIT_ZERO 0x00 + +// Masks for all bit ranges +#define CMD_MASK 0x80 +#define FUNCTSEL_MASK 0x60 +#define BITPOL_MASK 0x10 +#define SPEEDSEL_MASK 0x0C +#define MODSEL_MASK 0x02 +#define PARMSEL_MASK 0x70 +#define PARMSET_MASK 0x0E +#define VERSION_MASK 0x1C + +// Command or config bit +#define CMD_COMM 0x81 +#define CMD_CONFIG 0x01 + +// Function select bits +#define FUNCTSEL_BIT 0x00 +#define FUNCTSEL_SEARCHON 0x30 +#define FUNCTSEL_SEARCHOFF 0x20 +#define FUNCTSEL_RESET 0x40 +#define FUNCTSEL_CHMOD 0x60 + +// Bit polarity/Pulse voltage bits +#define BITPOL_ONE 0x10 +#define BITPOL_ZERO 0x00 +#define BITPOL_5V 0x00 +#define BITPOL_12V 0x10 + +// One Wire speed bits +#define SPEEDSEL_STD 0x00 +#define SPEEDSEL_FLEX 0x04 +#define SPEEDSEL_OD 0x08 +#define SPEEDSEL_PULSE 0x0C + +// Data/Command mode select bits +#define MODSEL_DATA 0x00 +#define MODSEL_COMMAND 0x02 + +// 5V Follow Pulse select bits (If 5V pulse +// will be following the next byte or bit.) +#define PRIME5V_TRUE 0x02 +#define PRIME5V_FALSE 0x00 + +// Parameter select bits +#define PARMSEL_PARMREAD 0x00 +#define PARMSEL_SLEW 0x10 +#define PARMSEL_12VPULSE 0x20 +#define PARMSEL_5VPULSE 0x30 +#define PARMSEL_WRITE1LOW 0x40 +#define PARMSEL_SAMPLEOFFSET 0x50 +#define PARMSEL_ACTIVEPULLUPTIME 0x60 +#define PARMSEL_BAUDRATE 0x70 + +// Pull down slew rate. +#define PARMSET_Slew15Vus 0x00 +#define PARMSET_Slew2p2Vus 0x02 +#define PARMSET_Slew1p65Vus 0x04 +#define PARMSET_Slew1p37Vus 0x06 +#define PARMSET_Slew1p1Vus 0x08 +#define PARMSET_Slew0p83Vus 0x0A +#define PARMSET_Slew0p7Vus 0x0C +#define PARMSET_Slew0p55Vus 0x0E + +// 12V programming pulse time table +#define PARMSET_32us 0x00 +#define PARMSET_64us 0x02 +#define PARMSET_128us 0x04 +#define PARMSET_256us 0x06 +#define PARMSET_512us 0x08 +#define PARMSET_1024us 0x0A +#define PARMSET_2048us 0x0C +#define PARMSET_infinite 0x0E + +// 5V strong pull up pulse time table +#define PARMSET_16p4ms 0x00 +#define PARMSET_65p5ms 0x02 +#define PARMSET_131ms 0x04 +#define PARMSET_262ms 0x06 +#define PARMSET_524ms 0x08 +#define PARMSET_1p05s 0x0A +#define PARMSET_2p10s 0x0C +#define PARMSET_infinite 0x0E + +// Write 1 low time +#define PARMSET_Write8us 0x00 +#define PARMSET_Write9us 0x02 +#define PARMSET_Write10us 0x04 +#define PARMSET_Write11us 0x06 +#define PARMSET_Write12us 0x08 +#define PARMSET_Write13us 0x0A +#define PARMSET_Write14us 0x0C +#define PARMSET_Write15us 0x0E + +// Data sample offset and Write 0 recovery time +#define PARMSET_SampOff3us 0x00 +#define PARMSET_SampOff4us 0x02 +#define PARMSET_SampOff5us 0x04 +#define PARMSET_SampOff6us 0x06 +#define PARMSET_SampOff7us 0x08 +#define PARMSET_SampOff8us 0x0A +#define PARMSET_SampOff9us 0x0C +#define PARMSET_SampOff10us 0x0E + +// Active pull up on time +#define PARMSET_PullUp0p0us 0x00 +#define PARMSET_PullUp0p5us 0x02 +#define PARMSET_PullUp1p0us 0x04 +#define PARMSET_PullUp1p5us 0x06 +#define PARMSET_PullUp2p0us 0x08 +#define PARMSET_PullUp2p5us 0x0A +#define PARMSET_PullUp3p0us 0x0C +#define PARMSET_PullUp3p5us 0x0E + +// Baud rate bits +#define PARMSET_9600 0x00 +#define PARMSET_19200 0x02 +#define PARMSET_57600 0x04 +#define PARMSET_115200 0x06 + +// DS2480B program voltage available +#define DS2480PROG_MASK 0x20 + +// mode bit flags +#define MODE_NORMAL 0x00 +#define MODE_OVERDRIVE 0x01 +#define MODE_STRONG5 0x02 +#define MODE_PROGRAM 0x04 +#define MODE_BREAK 0x08 + +// Versions of DS2480 +#define VER_LINK 0x1C +#define VER_DS2480 0x08 +#define VER_DS2480B 0x0C + +// exportable functions defined in ds2480ut.c +SMALLINT DS2480Detect(int portnum); +SMALLINT DS2480ChangeBaud(int portnum, uchar newbaud); + +// link functions from win32lnk.c or other link files +SMALLINT OpenCOM(int portnum, const char *port_zstr); +int OpenCOMEx(const char *port_zstr); +void CloseCOM(int portnum); +void FlushCOM(int portnum); +SMALLINT WriteCOM(int portnum, int outlen, uchar *outbuf); +int ReadCOM(int portnum, int inlen, uchar *inbuf); +void BreakCOM(int portnum); +void SetBaudCOM(int portnum, uchar new_baud); diff --git a/src/plugins/pro1_data_zip/ow/ds2480ut.c b/src/plugins/pro1_data_zip/ow/ds2480ut.c new file mode 100644 index 0000000..57bc4fa --- /dev/null +++ b/src/plugins/pro1_data_zip/ow/ds2480ut.c @@ -0,0 +1,225 @@ +//--------------------------------------------------------------------------- +// Copyright (C) 2000 Dallas Semiconductor Corporation, All Rights Reserved. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL DALLAS SEMICONDUCTOR BE LIABLE FOR ANY CLAIM, DAMAGES +// OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// +// Except as contained in this notice, the name of Dallas Semiconductor +// shall not be used except as stated in the Dallas Semiconductor +// Branding Policy. +//--------------------------------------------------------------------------- +// +// ds2480ut.c - DS2480B utility functions. +// +// Version: 2.01 +// +// History: 1.00 -> 1.01 Default PDSRC changed from 0.83 to 1.37V/us +// in DS2480Detect. Changed to use msDelay instead +// of Delay. +// 1.01 -> 1.02 Changed global declarations from 'uchar' to 'int'. +// Changed DSO/WORT from 7 to 10us in DS2480Detect. +// 1.02 -> 1.03 Removed caps in #includes for Linux capatibility +// 1.03 -> 2.00 Changed 'MLan' to 'ow'. Added support for +// multiple ports. Changed W1LT to 8us. +// 2.00 -> 2.01 Added error handling. Added circular-include check. +// 2.01 -> 2.10 Added raw memory error handling and SMALLINT +// 2.10 -> 3.00 Added memory bank functionality +// Added file I/O operations +// + +#include "ownet.h" +#include "ds2480.h" + +// global DS2480B state +SMALLINT ULevel[MAX_PORTNUM]; // current DS2480B 1-Wire Net level +SMALLINT UBaud[MAX_PORTNUM]; // current DS2480B baud rate +SMALLINT UMode[MAX_PORTNUM]; // current DS2480B command or data mode state +SMALLINT USpeed[MAX_PORTNUM]; // current DS2480B 1-Wire Net communication speed +SMALLINT UVersion[MAX_PORTNUM]; // current DS2480B version + +//--------------------------------------------------------------------------- +// Attempt to resyc and detect a DS2480B +// +// 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to +// OpenCOM to indicate the port number. +// +// Returns: TRUE - DS2480B detected successfully +// FALSE - Could not detect DS2480B +// +SMALLINT DS2480Detect(int portnum) +{ + uchar sendpacket[10],readbuffer[10]; + uchar sendlen=0; + + // reset modes + UMode[portnum] = MODSEL_COMMAND; + UBaud[portnum] = PARMSET_9600; + USpeed[portnum] = SPEEDSEL_FLEX; + + // set the baud rate to 9600 + SetBaudCOM(portnum,(uchar)UBaud[portnum]); + + // send a break to reset the DS2480 + BreakCOM(portnum); + + // delay to let line settle + msDelay(2); + + // flush the buffers + FlushCOM(portnum); + + // send the timing byte + sendpacket[0] = 0xC1; + if (WriteCOM(portnum,1,sendpacket) != 1) + { + OWERROR(OWERROR_WRITECOM_FAILED); + return FALSE; + } + + // delay to let line settle + msDelay(4); + + // set the FLEX configuration parameters + // default PDSRC = 1.37Vus + sendpacket[sendlen++] = CMD_CONFIG | PARMSEL_SLEW | PARMSET_Slew1p37Vus; + // default W1LT = 10us + sendpacket[sendlen++] = CMD_CONFIG | PARMSEL_WRITE1LOW | PARMSET_Write10us; + // default DSO/WORT = 8us + sendpacket[sendlen++] = CMD_CONFIG | PARMSEL_SAMPLEOFFSET | PARMSET_SampOff8us; + + // construct the command to read the baud rate (to test command block) + sendpacket[sendlen++] = CMD_CONFIG | PARMSEL_PARMREAD | (PARMSEL_BAUDRATE >> 3); + + // also do 1 bit operation (to test 1-Wire block) + sendpacket[sendlen++] = CMD_COMM | FUNCTSEL_BIT | UBaud[portnum] | BITPOL_ONE; + + // flush the buffers + FlushCOM(portnum); + + // send the packet + if (WriteCOM(portnum,sendlen,sendpacket)) + { + // read back the response + if (ReadCOM(portnum,5,readbuffer) == 5) + { + // look at the baud rate and bit operation + // to see if the response makes sense + if (((readbuffer[3] & 0xF1) == 0x00) && + ((readbuffer[3] & 0x0E) == UBaud[portnum]) && + ((readbuffer[4] & 0xF0) == 0x90) && + ((readbuffer[4] & 0x0C) == UBaud[portnum])) + return TRUE; + else + OWERROR(OWERROR_DS2480_BAD_RESPONSE); + } + else + OWERROR(OWERROR_READCOM_FAILED); + } + else + OWERROR(OWERROR_WRITECOM_FAILED); + + return FALSE; +} + +//--------------------------------------------------------------------------- +// Change the DS2480B from the current baud rate to the new baud rate. +// +// 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to +// OpenCOM to indicate the port number. +// 'newbaud' - the new baud rate to change to, defined as: +// PARMSET_9600 0x00 +// PARMSET_19200 0x02 +// PARMSET_57600 0x04 +// PARMSET_115200 0x06 +// +// Returns: current DS2480B baud rate. +// +SMALLINT DS2480ChangeBaud(int portnum, uchar newbaud) +{ + uchar rt=FALSE; + uchar readbuffer[5],sendpacket[5],sendpacket2[5]; + uchar sendlen=0,sendlen2=0; + + // see if diffenent then current baud rate + if (UBaud[portnum] == newbaud) + return UBaud[portnum]; + else + { + // build the command packet + // check if correct mode + if (UMode[portnum] != MODSEL_COMMAND) + { + UMode[portnum] = MODSEL_COMMAND; + sendpacket[sendlen++] = MODE_COMMAND; + } + // build the command + sendpacket[sendlen++] = CMD_CONFIG | PARMSEL_BAUDRATE | newbaud; + + // flush the buffers + FlushCOM(portnum); + + // send the packet + if (!WriteCOM(portnum,sendlen,sendpacket)) + { + OWERROR(OWERROR_WRITECOM_FAILED); + rt = FALSE; + } + else + { + // make sure buffer is flushed + msDelay(5); + + // change our baud rate + SetBaudCOM(portnum,newbaud); + UBaud[portnum] = newbaud; + + // wait for things to settle + msDelay(5); + + // build a command packet to read back baud rate + sendpacket2[sendlen2++] = CMD_CONFIG | PARMSEL_PARMREAD | (PARMSEL_BAUDRATE >> 3); + + // flush the buffers + FlushCOM(portnum); + + // send the packet + if (WriteCOM(portnum,sendlen2,sendpacket2)) + { + // read back the 1 byte response + if (ReadCOM(portnum,1,readbuffer) == 1) + { + // verify correct baud + if (((readbuffer[0] & 0x0E) == (sendpacket[sendlen-1] & 0x0E))) + rt = TRUE; + else + OWERROR(OWERROR_DS2480_WRONG_BAUD); + } + else + OWERROR(OWERROR_READCOM_FAILED); + } + else + OWERROR(OWERROR_WRITECOM_FAILED); + } + } + + // if lost communication with DS2480 then reset + if (rt != TRUE) + DS2480Detect(portnum); + + return UBaud[portnum]; +} diff --git a/src/plugins/pro1_data_zip/ow/linuxlnk.c b/src/plugins/pro1_data_zip/ow/linuxlnk.c new file mode 100644 index 0000000..775c907 --- /dev/null +++ b/src/plugins/pro1_data_zip/ow/linuxlnk.c @@ -0,0 +1,399 @@ +//--------------------------------------------------------------------------- +// Copyright (C) 2000 Dallas Semiconductor Corporation, All Rights Reserved. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL DALLAS SEMICONDUCTOR BE LIABLE FOR ANY CLAIM, DAMAGES +// OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// +// Except as contained in this notice, the name of Dallas Semiconductor +// shall not be used except as stated in the Dallas Semiconductor +// Branding Policy. +//--------------------------------------------------------------------------- +// +// linuxlnk.C - COM functions required by MLANLL.C, MLANTRNU, MLANNETU.C and +// MLanFile.C for MLANU to communicate with the DS2480 based +// Universal Serial Adapter 'U'. Fill in the platform specific code. +// +// Version: 1.02 +// +// History: 1.00 -> 1.01 Added function msDelay. +// +// 1.01 -> 1.02 Changed to generic OpenCOM/CloseCOM for easier +// use with other platforms. +// + +//-------------------------------------------------------------------------- +// Copyright (C) 1998 Andrea Chambers and University of Newcastle upon Tyne, +// All Rights Reserved. +//-------------------------------------------------------------------------- +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE UNIVERSITY OF NEWCASTLE UPON TYNE OR ANDREA CHAMBERS +// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH +// THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +//--------------------------------------------------------------------------- +// +// LinuxLNK.C - COM functions required by MLANLLU.C, MLANTRNU.C, MLANNETU.C +// and MLanFile.C for MLANU to communicate with the DS2480 based +// Universal Serial Adapter 'U'. Platform specific code. +// +// Version: 2.01 +// History: 1.02 -> 1.03 modifications by David Smiczek +// Changed to use generic OpenCOM/CloseCOM +// Pass port name to OpenCOM instead of hard coded +// Changed msDelay to handle long delays +// Reformatted to look like 'TODO.C' +// Added #include "ds2480.h" to use constants. +// Added function SetBaudCOM() +// Added function msGettick() +// Removed delay from WriteCOM(), used tcdrain() +// Added wait for byte available with timeout using +// select() in ReadCOM() +// +// 1.03 -> 2.00 Support for multiple ports. Include "ownet.h". Use +// 'uchar'. Reorder functions. Provide correct +// return values to OpenCOM. Replace 'makeraw' call. +// Should now be POSIX. +// 2.00 -> 2.01 Added support for owError library. +// + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ds2480.h" +#include "ownet.h" + +// LinuxLNK global +int fd[MAX_PORTNUM]; +SMALLINT fd_init; +struct termios origterm; + + +//--------------------------------------------------------------------------- +// Attempt to open a com port. Keep the handle in ComID. +// Set the starting baud rate to 9600. +// +// 'portnum' - number 0 to MAX_PORTNUM-1. This number provided will +// be used to indicate the port number desired when calling +// all other functions in this library. +// +// +// Returns: the port number if it was succesful otherwise -1 +// +int OpenCOMEx(const char *port_zstr) +{ + int i; + int portnum; + + if(!fd_init) + { + for(i=0; i=0 && !fd[portnum], + OWERROR_PORTNUM_ERROR, FALSE ); + + fd[portnum] = open(port_zstr, O_RDWR); + if (fd[portnum]<0) + { + OWERROR(OWERROR_GET_SYSTEM_RESOURCE_FAILED); + return FALSE; // changed (2.00), used to return fd; + } + rc = tcgetattr (fd[portnum], &t); + if (rc < 0) + { + int tmp; + tmp = errno; + close(fd[portnum]); + errno = tmp; + OWERROR(OWERROR_SYSTEM_RESOURCE_INIT_FAILED); + return FALSE; // changed (2.00), used to return rc; + } + + cfsetospeed(&t, B9600); + cfsetispeed (&t, B9600); + + // Get terminal parameters. (2.00) removed raw + tcgetattr(fd[portnum],&t); + // Save original settings. + origterm = t; + + // Set to non-canonical mode, and no RTS/CTS handshaking + t.c_iflag &= ~(BRKINT|ICRNL|IGNCR|INLCR|INPCK|ISTRIP|IXON|IXOFF|PARMRK); + t.c_iflag |= IGNBRK|IGNPAR; + t.c_oflag &= ~(OPOST); + t.c_cflag &= ~(CRTSCTS|CSIZE|HUPCL|PARENB); + t.c_cflag |= (CLOCAL|CS8|CREAD); + t.c_lflag &= ~(ECHO|ECHOE|ECHOK|ECHONL|ICANON|IEXTEN|ISIG); + t.c_cc[VMIN] = 0; + t.c_cc[VTIME] = 3; + + rc = tcsetattr(fd[portnum], TCSAFLUSH, &t); + tcflush(fd[portnum],TCIOFLUSH); + + if (rc < 0) + { + int tmp; + tmp = errno; + close(fd[portnum]); + errno = tmp; + OWERROR(OWERROR_SYSTEM_RESOURCE_INIT_FAILED); + return FALSE; // changed (2.00), used to return rc; + } + + return TRUE; // changed (2.00), used to return fd; +} + + +//--------------------------------------------------------------------------- +// Closes the connection to the port. +// +// 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to +// OpenCOM to indicate the port number. +// +void CloseCOM(int portnum) +{ + // restore tty settings + tcsetattr(fd[portnum], TCSAFLUSH, &origterm); + FlushCOM(portnum); + close(fd[portnum]); + fd[portnum] = 0; +} + + +//-------------------------------------------------------------------------- +// Write an array of bytes to the COM port, verify that it was +// sent out. Assume that baud rate has been set. +// +// 'portnum' - number 0 to MAX_PORTNUM-1. This number provided will +// be used to indicate the port number desired when calling +// all other functions in this library. +// Returns 1 for success and 0 for failure +// +SMALLINT WriteCOM(int portnum, int outlen, uchar *outbuf) +{ + long count = outlen; + int i = write(fd[portnum], outbuf, outlen); + + tcdrain(fd[portnum]); + return (i == count); +} + + +//-------------------------------------------------------------------------- +// Read an array of bytes to the COM port, verify that it was +// sent out. Assume that baud rate has been set. +// +// 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to +// OpenCOM to indicate the port number. +// 'outlen' - number of bytes to write to COM port +// 'outbuf' - pointer ot an array of bytes to write +// +// Returns: TRUE(1) - success +// FALSE(0) - failure +// +int ReadCOM(int portnum, int inlen, uchar *inbuf) +{ + // loop to wait until each byte is available and read it + for (int cnt = 0; cnt < inlen; cnt++) + { + if (read(fd[portnum],&inbuf[cnt],1) != 1) + return cnt; + } + + // success, so return desired length + return inlen; +} + + +//--------------------------------------------------------------------------- +// Description: +// flush the rx and tx buffers +// +// 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to +// OpenCOM to indicate the port number. +// +void FlushCOM(int portnum) +{ + tcflush(fd[portnum], TCIOFLUSH); +} + + +//-------------------------------------------------------------------------- +// Description: +// Send a break on the com port for at least 2 ms +// +// 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to +// OpenCOM to indicate the port number. +// +void BreakCOM(int portnum) +{ + int duration = 0; // see man termios break may be + tcsendbreak(fd[portnum], duration); // too long +} + + +//-------------------------------------------------------------------------- +// Set the baud rate on the com port. +// +// 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to +// OpenCOM to indicate the port number. +// 'new_baud' - new baud rate defined as +// PARMSET_9600 0x00 +// PARMSET_19200 0x02 +// PARMSET_57600 0x04 +// PARMSET_115200 0x06 +// +void SetBaudCOM(int portnum, uchar new_baud) +{ + struct termios t; + speed_t baud; + int rc; + + // read the attribute structure + rc = tcgetattr(fd[portnum], &t); + if (rc < 0) + { + close(fd[portnum]); + return; + } + + // convert parameter to linux baud rate + switch(new_baud) + { + case PARMSET_9600: + baud = B9600; + break; + case PARMSET_19200: + baud = B19200; + break; + case PARMSET_57600: + baud = B57600; + break; + case PARMSET_115200: + baud = B115200; + break; + default: + baud = 0; + } + + // set baud in structure + cfsetospeed(&t, baud); + cfsetispeed(&t, baud); + + // change baud on port + rc = tcsetattr(fd[portnum], TCSAFLUSH, &t); + if (rc < 0) + close(fd[portnum]); +} + + +//-------------------------------------------------------------------------- +// Get the current millisecond tick count. Does not have to represent +// an actual time, it just needs to be an incrementing timer. +// +long msGettick(void) +{ + struct timezone tmzone; + struct timeval tmval; + long ms; + + gettimeofday(&tmval,&tmzone); + ms = (tmval.tv_sec & 0xFFFF) * 1000 + tmval.tv_usec / 1000; + return ms; +} + + +//-------------------------------------------------------------------------- +// Description: +// Delay for at least 'len' ms +// +void msDelay(int len) +{ + struct timespec s; // Set aside memory space on the stack + + s.tv_sec = len / 1000; + s.tv_nsec = (len - (s.tv_sec * 1000)) * 1000000; + nanosleep(&s, NULL); +} + diff --git a/src/plugins/pro1_data_zip/ow/owerr.c b/src/plugins/pro1_data_zip/ow/owerr.c new file mode 100644 index 0000000..f0d797f --- /dev/null +++ b/src/plugins/pro1_data_zip/ow/owerr.c @@ -0,0 +1,345 @@ +//--------------------------------------------------------------------------- +// Copyright (C) 2000 Dallas Semiconductor Corporation, All Rights Reserved. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL DALLAS SEMICONDUCTOR BE LIABLE FOR ANY CLAIM, DAMAGES +// OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// +// Except as contained in this notice, the name of Dallas Semiconductor +// shall not be used except as stated in the Dallas Semiconductor +// Branding Policy. +//--------------------------------------------------------------------------- +// +// owerr.c - Library functions for error handling with 1-Wire library +// +// Version: 1.00 +// + +#include +#ifndef _WIN32_WCE +#include +#endif +#include "ownet.h" + +#ifndef SIZE_OWERROR_STACK + #ifdef SMALL_MEMORY_TARGET + //for small memory, only hole 1 error + #define SIZE_OWERROR_STACK 1 + #else + #define SIZE_OWERROR_STACK 10 + #endif +#endif + +//--------------------------------------------------------------------------- +// Variables +//--------------------------------------------------------------------------- + +// Error Struct for holding error information. +// In DEBUG, this will also hold the line number and filename. +typedef struct +{ + int owErrorNum; +#ifdef DEBUG + int lineno; + char *filename; +#endif +} owErrorStruct; + +// Ring-buffer used for stack. +// In case of overflow, deepest error is over-written. +static owErrorStruct owErrorStack[SIZE_OWERROR_STACK]; + +// Stack pointer to top-most error. +static int owErrorPointer = 0; + + +//--------------------------------------------------------------------------- +// Functions Definitions +//--------------------------------------------------------------------------- +int owGetErrorNum(void); +void owClearError(void); +int owHasErrors(void); +#ifdef DEBUG + void owRaiseError(int,int,char*); +#else + void owRaiseError(int); +#endif +#ifndef SMALL_MEMORY_TARGET + void owPrintErrorMsg(FILE *); + void owPrintErrorMsgStd(); + char *owGetErrorMsg(int); +#endif + + +//-------------------------------------------------------------------------- +// The 'owGetErroNum' returns the error code of the top-most error on the +// error stack. NOTE: This function has the side effect of popping the +// current error off the stack. All successive calls to 'owGetErrorNum' +// will further clear the error stack. +// +// For list of error codes, see 'ownet.h' +// +// Returns: int : The error code of the top-most error on the stack +// +int owGetErrorNum(void) +{ + int i = owErrorStack[ owErrorPointer ].owErrorNum; + owErrorStack[ owErrorPointer ].owErrorNum = 0; + if(!owErrorPointer) + owErrorPointer = SIZE_OWERROR_STACK - 1; + else + owErrorPointer = (owErrorPointer - 1); + return i; +} + +//-------------------------------------------------------------------------- +// The 'owClearError' clears all the errors. +// +void owClearError(void) +{ + owErrorStack[ owErrorPointer ].owErrorNum = 0; +} + +//-------------------------------------------------------------------------- +// The 'owHasErrors' is a boolean test function which tests whether or not +// a valid error is waiting on the stack. +// +// Returns: TRUE (1) : When there are errors on the stack. +// FALSE (0): When stack's errors are set to 0, or NO_ERROR_SET. +// +int owHasErrors(void) +{ + if(owErrorStack[ owErrorPointer ].owErrorNum) + return 1; //TRUE + else + return 0; //FALSE +} + +#ifdef DEBUG + //-------------------------------------------------------------------------- + // The 'owRaiseError' is the method for raising an error onto the error + // stack. + // + // Arguments: int err - the error code you wish to raise. + // int lineno - DEBUG only - the line number where it was raised + // char* filename - DEBUG only - the file name where it occured. + // + void owRaiseError(int err, int lineno, char* filename) + { + owErrorPointer = (owErrorPointer + 1) % SIZE_OWERROR_STACK; + owErrorStack[ owErrorPointer ].owErrorNum = err; + owErrorStack[ owErrorPointer ].lineno = lineno; + owErrorStack[ owErrorPointer ].filename = filename; + } +#else + //-------------------------------------------------------------------------- + // The 'owRaiseError' is the method for raising an error onto the error + // stack. + // + // Arguments: int err - the error code you wish to raise. + // + void owRaiseError(int err) + { + owErrorPointer = (owErrorPointer + 1) % SIZE_OWERROR_STACK; + owErrorStack[ owErrorPointer ].owErrorNum = err; + } +#endif + + +// SMALL_MEMORY_TARGET - embedded microcontrollers, where these +// messaging functions might not make any sense. +#ifndef SMALL_MEMORY_TARGET + //Array of meaningful error messages to associate with codes. + //Not used on targets with low memory (i.e. PIC). + static char *owErrorMsg[125] = + { + /*000*/ "No Error Was Set", + /*001*/ "No Devices found on 1-Wire Network", + /*002*/ "1-Wire Net Reset Failed", + /*003*/ "Search ROM Error: Couldn't locate next device on 1-Wire", + /*004*/ "Access Failed: Could not select device", + /*005*/ "DS2480B Adapter Not Detected", + /*006*/ "DS2480B: Wrong Baud", + /*007*/ "DS2480B: Bad Response", + /*008*/ "Open COM Failed", + /*009*/ "Write COM Failed", + /*010*/ "Read COM Failed", + /*011*/ "Data Block Too Large", + /*012*/ "Block Transfer failed", + /*013*/ "Program Pulse Failed", + /*014*/ "Program Byte Failed", + /*015*/ "Write Byte Failed", + /*016*/ "Read Byte Failed", + /*017*/ "Write Verify Failed", + /*018*/ "Read Verify Failed", + /*019*/ "Write Scratchpad Failed", + /*020*/ "Copy Scratchpad Failed", + /*021*/ "Incorrect CRC Length", + /*022*/ "CRC Failed", + /*023*/ "Failed to acquire a necessary system resource", + /*024*/ "Failed to initialize system resource", + /*025*/ "Data too long to fit on specified device.", + /*026*/ "Read exceeds memory bank end.", + /*027*/ "Write exceeds memory bank end.", + /*028*/ "Device select failed", + /*029*/ "Read Scratch Pad verify failed.", + /*030*/ "Copy scratchpad complete not found", + /*031*/ "Erase scratchpad complete not found", + /*032*/ "Address read back from scrachpad was incorrect", + /*033*/ "Read page with extra-info not supported by this memory bank", + /*034*/ "Read page packet with extra-info not supported by this memory bank", + /*035*/ "Length of packet requested exceeds page size", + /*036*/ "Invalid length in packet", + /*037*/ "Program pulse required but not available", + /*038*/ "Trying to access a read-only memory bank", + /*039*/ "Current bank is not general purpose memory", + /*040*/ "Read back from write compare is incorrect, page may be locked", + /*041*/ "Invalid page number for this memory bank", + /*042*/ "Read page with CRC not supported by this memory bank", + /*043*/ "Read page with CRC and extra-info not supported by this memory bank", + /*044*/ "Read back from write incorrect, could not lock page", + /*045*/ "Read back from write incorrect, could not lock redirect byte", + /*046*/ "The read of the status was not completed.", + /*047*/ "Page redirection not supported by this memory bank", + /*048*/ "Lock Page redirection not supported by this memory bank", + /*049*/ "Read back byte on EPROM programming did not match.", + /*050*/ "Can not write to a page that is locked.", + /*051*/ "Can not lock a redirected page that has already been locked.", + /*052*/ "Trying to redirect a locked redirected page.", + /*053*/ "Trying to lock a page that is already locked.", + /*054*/ "Trying to write to a memory bank that is write protected.", + /*055*/ "Error due to not matching MAC.", + /*056*/ "Memory Bank is write protected.", + /*057*/ "Secret is write protected, can not Load First Secret.", + /*058*/ "Error in Reading Scratchpad after Computing Next Secret.", + /*059*/ "Load Error from Loading First Secret.", + /*060*/ "Power delivery required but not available", + /*061*/ "Not a valid file name.", + /*062*/ "Unable to Create a Directory in this part.", + /*063*/ "That file already exists.", + /*064*/ "The directory is not empty.", + /*065*/ "The wrong type of part for this operation.", + /*066*/ "The max len for this file is too small.", + /*067*/ "This is not a write once bank.", + /*068*/ "The file can not be found.", + /*069*/ "There is not enough space available.", + /*070*/ "There is not a page to match that bit in the bitmap.", + /*071*/ "There are no jobs for EPROM parts.", + /*072*/ "Function not supported to modify attributes.", + /*073*/ "Handle is not in use.", + /*074*/ "Tring to read a write only file.", + /*075*/ "There is no handle available for use.", + /*076*/ "The directory provided is an invalid directory.", + /*077*/ "Handle does not exist.", + /*078*/ "Serial Number did not match with current job.", + /*079*/ "Can not program EPROM because a non-EPROM part on the network.", + /*080*/ "Write protect redirection byte is set.", + /*081*/ "There is an inappropriate directory length.", + /*082*/ "The file has already been terminated.", + /*083*/ "Failed to read memory page of iButton part.", + /*084*/ "Failed to match scratchpad of iButton part.", + /*085*/ "Failed to erase scratchpad of iButton part.", + /*086*/ "Failed to read scratchpad of iButton part.", + /*087*/ "Failed to execute SHA function on SHA iButton.", + /*088*/ "SHA iButton did not return a status completion byte.", + /*089*/ "Write data page failed.", + /*090*/ "Copy secret into secret memory pages failed.", + /*091*/ "Bind unique secret to iButton failed.", + /*092*/ "Could not install secret into user token.", + /*093*/ "Transaction Incomplete: signature did not match.", + /*094*/ "Transaction Incomplete: could not sign service data.", + /*095*/ "User token did not provide a valid authentication response.", + /*096*/ "Failed to answer a challenge on the user token.", + /*097*/ "Failed to create a challenge on the coprocessor.", + /*098*/ "Transaction Incomplete: service data was not valid.", + /*099*/ "Transaction Incomplete: service data was not updated.", + /*100*/ "Unrecoverable, catastrophic service failure occured.", + /*101*/ "Load First Secret from scratchpad data failed.", + /*102*/ "Failed to match signature of user's service data.", + /*103*/ "Subkey out of range for the DS1991.", + /*104*/ "Block ID out of range for the DS1991", + /*105*/ "Password is enabled", + /*106*/ "Password is invalid", + /*107*/ "This memory bank has no read only password", + /*108*/ "This memory bank has no read/write password", + /*109*/ "1-Wire is shorted", + /*110*/ "Error communicating with 1-Wire adapter", + /*111*/ "CopyScratchpad failed: Ending Offset must go to end of page", + /*112*/ "WriteScratchpad failed: Ending Offset must go to end of page", + /*113*/ "Mission can not be stopped while one is not in progress", + /*114*/ "Error stopping the mission", + /*115*/ "Port number is outside (0,MAX_PORTNUM) interval", + /*116*/ "Level of the 1-Wire was not changed", + /*117*/ "Both the Read Only and Read Write Passwords must be set", + /*118*/ "Failure to change latch state." + /*119*/ "Could not open usb port through libusb", + /*120*/ "Libusb DS2490 port already opened", + /*121*/ "Failed to set libusb configuration", + /*122*/ "Failed to claim libusb interface", + /*123*/ "Failed to set libusb altinterface", + /*124*/ "No adapter found at this port number" + }; + + char *owGetErrorMsg(int err) + { + return owErrorMsg[err]; + } + +#ifndef __C51__ + //-------------------------------------------------------------------------- + // The 'owPrintErrorMsg' is the method for printing an error from the stack. + // The destination for the print is specified by the argument, fileno, which + // can be stderr, stdout, or a log file. In non-debug mode, the output is + // of the form: + // Error num: Error msg + // + // In debug-mode, the output is of the form: + // Error num: filename line#: Error msg + // + // NOTE: This function has the side-effect of popping the error off the stack. + // + // Arguments: FILE*: the destination for printing. + // + void owPrintErrorMsg(FILE *filenum) + { + #ifdef DEBUG + int l = owErrorStack[ owErrorPointer ].lineno; + char *f = owErrorStack[ owErrorPointer ].filename; + int err = owGetErrorNum(); + fprintf(filenum,"Error %d: %s line %d: %s\r\n",err,f,l,owErrorMsg[err]); + #else + int err = owGetErrorNum(); + fprintf(filenum,"Error %d: %s\r\n",err,owErrorMsg[err]); + #endif + } +#endif //__C51__ + + // Same as above, except uses default printf output + void owPrintErrorMsgStd() + { + #ifdef DEBUG + int l = owErrorStack[ owErrorPointer ].lineno; + char *f = owErrorStack[ owErrorPointer ].filename; + int err = owGetErrorNum(); + printf("Error %d: %s line %d: %s\r\n",err,f,l,owErrorMsg[err]); + #else + int err = owGetErrorNum(); + printf("Error %d: %s\r\n",err,owErrorMsg[err]); + #endif + } +#endif + diff --git a/src/plugins/pro1_data_zip/ow/owfile.h b/src/plugins/pro1_data_zip/ow/owfile.h new file mode 100644 index 0000000..835f654 --- /dev/null +++ b/src/plugins/pro1_data_zip/ow/owfile.h @@ -0,0 +1,196 @@ +/*--------------------------------------------------------------------------- + * Copyright (C) 2000 Dallas Semiconductor Corporation, All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL DALLAS SEMICONDUCTOR BE LIABLE FOR ANY CLAIM, DAMAGES + * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of Dallas Semiconductor + * shall not be used except as stated in the Dallas Semiconductor + * Branding Policy. + *-------------------------------------------------------------------------- + * + * owFile.h - Contains the types and constants for file I/O. + * + * version 1.00 + */ + +#include "ownet.h" + +#ifndef OWFILE_H +#define OWFILE_H +#define MAX_NUM_PGS 256 /* this is for max pages part might have */ + /* increase if you are going to use parts */ + /* with more than 256 pages. */ +#define PAGE_TYPE uchar /* change if the page number can be > 256 */ +#define FILE_NAME_LEN 7 /* the length of a new file */ +#define FIRST_FOUND 204 /* don't know how many now so return max */ +/* Used in internal function Read_Page and page cache */ +#define STATUSMEM 0x80 +#define REDIRMEM 0x40 +#define REGMEM 0 +#define DEPTH 254 +#define CACHE_TIMEOUT 8000 +/* Directory options */ +#define SET_DIR 0 +#define READ_DIR 1 +/* program Job constants */ +#define PJOB_NONE 0 +#define PJOB_WRITE 1 +#define PJOB_REDIR 2 +#define PJOB_ADD 3 +#define PJOB_TERM 4 +#define PJOB_START 0x80 +#define PJOB_MASK 0x7F +#define APPEND 1 + +/* external file information structure */ +typedef struct +{ + uchar Name[4]; /* 4 */ + uchar Ext; /* 1 */ + uchar Spage; /* 1 */ + uchar NumPgs; /* 1 */ + uchar Attrib; /* 1 */ + uchar BM[32]; /* 32 */ +} FileEntry; + +/* structure use when reading or changing the current directory */ +typedef struct +{ + uchar NumEntries; /* number of entries in path 0-10 */ + char Ref; /* reference character '\' or '.' */ + char Entries[10][4]; /* sub-directory entry names */ +} DirectoryPath; + +/* internal file information structure */ +typedef struct +{ + uchar Name[4]; /* 4 File/Directory name */ + uchar Ext; /* 1 File/Directory extension */ + uchar Spage; /* 1 Start page */ + uchar NumPgs; /* 1 Number of pages */ + uchar Attrib; /* 1 Attribute 0x01 for readonly 0x02 for hidden */ + uchar Dpage; /* 1 Directory page this entry is in */ + uchar Offset; /* 1 Byte offset into directory page of entry */ + uchar Read; /* 1 Read = 1 if opened and 0 if created */ + uchar PDpage; /* 1 Previous directory page number */ +} FileInfo; + +/* current directory structure */ +typedef struct +{ + uchar ne; /* number of entries */ + struct { + uchar name[4]; /* name and extention of the sub-directory */ + PAGE_TYPE page; /* page the subdirectory starts on */ + uchar attrib; /* attribute of the directory */ + } Entry [10]; + uchar DRom[8]; /* rom that this directory is valid for */ +} CurrentDirectory; + +/* structure to hold the program job list ~ 7977 bytes */ +typedef struct +{ + uchar ERom[8]; /* rom of the program job target */ + uchar EBitmap[32]; /* bit map kept for */ + uchar OrgBitmap[32]; /* original bitmap */ + struct { + uchar wr; /* flag to indicate this page needs to be written */ + PAGE_TYPE len; /* length of data */ + uchar data[29]; /* data to write */ + uchar bm[4]; /* bitmap for bytes to write */ + } Page[MAX_NUM_PGS]; /* 256 possible jobs */ +} ProgramJob; + +/* type to hold a data entry in the DHash */ +typedef struct +{ + uchar ROM[8]; /* rom of device page is from */ + ulong Tstamp; /* time stamp when page void */ + uchar Fptr; /* forward pointer to next entry in chain */ + uchar Bptr; /* back pointer to previous entry in chain */ + uchar Hptr; /* hash pointer to hash position */ + PAGE_TYPE Page; /* page number */ + uchar Data[32]; /* page data including length */ + uchar Redir; /* redirection page */ +} Dentry; +#endif /* OWFILE_H */ + +/* function prototypes for owcache.c */ +void InitDHash(void); +uchar AddPage(int portnum, uchar *SNum, PAGE_TYPE pg, uchar *buf, int len); +SMALLINT FindPage(int portnum, uchar *SNum, PAGE_TYPE *page, uchar mflag, uchar time, + uchar *buf, int *len, uchar *space_num); +uchar FreePage(uchar ptr); + +/* function prototypes for owfile.c */ +SMALLINT owFirstFile(int, uchar *, FileEntry *); +SMALLINT owNextFile(int, uchar *, FileEntry *); +SMALLINT owOpenFile(int, uchar *, FileEntry *,short *); +SMALLINT owCreateFile(int, uchar *, int *, short *, FileEntry *); +SMALLINT owCloseFile(int, uchar *, short); +SMALLINT owReadFile(int, uchar *, short, uchar *, int,int *); +SMALLINT owRemoveDir(int, uchar *, FileEntry *); +SMALLINT owWriteFile(int, uchar *, short , uchar *, int ); +SMALLINT owDeleteFile(int, uchar *, FileEntry *); +SMALLINT owFormat(int, uchar *); +SMALLINT owAttribute(int, uchar *, short, FileEntry *); +SMALLINT owReNameFile(int, uchar *, short, FileEntry *); +SMALLINT owChangeDirectory(int, uchar *, DirectoryPath *); +SMALLINT owCreateDir(int, uchar *, FileEntry *); +DirectoryPath owGetCurrentDir(int, uchar *); +SMALLINT owWriteAddFile(int,uchar *,short,short,short,uchar *,int *); +SMALLINT owTerminateAddFile(int,uchar *,FileEntry *); +SMALLINT ReadBitMap(int, uchar *, uchar *); +SMALLINT WriteBitMap(int, uchar *, uchar *); +SMALLINT ReadNumEntry(int, uchar *, short , FileEntry *, + PAGE_TYPE *); +SMALLINT GetMaxWrite(int, uchar *, uchar *); +SMALLINT FindDirectoryInfo(int, uchar *, PAGE_TYPE *, FileInfo *); +SMALLINT ValidRom(int, uchar *); +SMALLINT BitMapChange(int, uchar *, uchar, uchar, uchar *); +SMALLINT Valid_FileName(FileEntry *); +void FindEmpties(int, uchar *, uchar *, PAGE_TYPE *, + PAGE_TYPE *); +int maxPages(int, uchar *); +void ChangeRom(int portnum, uchar *SNum); +PAGE_TYPE getLastPage(int, uchar *); + +/* function prototypes for owpgrw.c */ +SMALLINT Read_Page(int portnum, uchar *SNum, uchar *buff, uchar flag, + PAGE_TYPE *pg, int *len); +SMALLINT Write_Page(int portnum, uchar *SNum, uchar *buff, PAGE_TYPE page, int len); +SMALLINT ExtWrite(int portnum, uchar *SNum, uchar strt_page, uchar *file, int fllen, + uchar *BM); +SMALLINT ExtRead(int portnum, uchar *SNum, uchar *file, int start_page, + int maxlen, uchar del, uchar *BM, int *fl_len); +SMALLINT ExtendedRead_Page(int portnum, uchar *SNum, uchar *buff, PAGE_TYPE pg); + +/* function prototypes for owprgm.c */ +SMALLINT owCreateProgramJob(int, uchar *); +SMALLINT owDoProgramJob(int, uchar *); +SMALLINT isJob(int,uchar *); +SMALLINT isJobWritten(int,uchar *,PAGE_TYPE); +SMALLINT getJobData(int,uchar *,PAGE_TYPE,uchar *,int *); +SMALLINT setJobData(int,uchar *,PAGE_TYPE,uchar *,int); +SMALLINT setJobWritten(int,uchar *,PAGE_TYPE,SMALLINT); +SMALLINT getOrigBM(int,uchar *,uchar *); +SMALLINT setProgramJob(int,uchar *,uchar,int); +SMALLINT getProgramJob(int,uchar *,uchar *,int); +SMALLINT WriteJobByte(int, uchar *, PAGE_TYPE, short, uchar, short); +SMALLINT TerminatePage(int, uchar *, short, uchar *); diff --git a/src/plugins/pro1_data_zip/ow/owllu.c b/src/plugins/pro1_data_zip/ow/owllu.c new file mode 100644 index 0000000..c78cf95 --- /dev/null +++ b/src/plugins/pro1_data_zip/ow/owllu.c @@ -0,0 +1,831 @@ +//--------------------------------------------------------------------------- +// Copyright (C) 2000 Dallas Semiconductor Corporation, All Rights Reserved. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL DALLAS SEMICONDUCTOR BE LIABLE FOR ANY CLAIM, DAMAGES +// OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// +// Except as contained in this notice, the name of Dallas Semiconductor +// shall not be used except as stated in the Dallas Semiconductor +// Branding Policy. +//--------------------------------------------------------------------------- +// +// owLLU.C - Link Layer 1-Wire Net functions using the DS2480/DS2480B (U) +// serial interface chip. +// +// Version: 3.00 +// +// History: 1.00 -> 1.01 DS2480 version number now ignored in +// owTouchReset. +// 1.02 -> 1.03 Removed caps in #includes for Linux capatibility +// Removed #include +// Add #include "ownet.h" to define TRUE,FALSE +// 1.03 -> 2.00 Changed 'MLan' to 'ow'. Added support for +// multiple ports. +// 2.00 -> 2.01 Added error handling. Added circular-include check. +// 2.01 -> 2.10 Added raw memory error handling and SMALLINT +// 2.10 -> 3.00 Added memory bank functionality +// Added file I/O operations +// Added owReadBitPower and owWriteBytePower +// Added support for THE LINK +// Updated owLevel to match AN192 +// + +#include "ownet.h" +#include "ds2480.h" + +int dodebug=0; + +// external globals +extern SMALLINT ULevel[MAX_PORTNUM]; // current DS2480B 1-Wire Net level +extern SMALLINT UBaud[MAX_PORTNUM]; // current DS2480B baud rate +extern SMALLINT UMode[MAX_PORTNUM]; // current DS2480B command or data mode state +extern SMALLINT USpeed[MAX_PORTNUM]; // current DS2480B 1-Wire Net communication speed +extern SMALLINT UVersion[MAX_PORTNUM]; // current DS2480B version + +// new global for DS1994/DS2404/DS1427. If TRUE, puts a delay in owTouchReset to compensate for alarming clocks. +SMALLINT FAMILY_CODE_04_ALARM_TOUCHRESET_COMPLIANCE = FALSE; // default owTouchReset to quickest response. + +// local varable flag, true if program voltage available +static SMALLINT ProgramAvailable[MAX_PORTNUM]; + +//-------------------------------------------------------------------------- +// Reset all of the devices on the 1-Wire Net and return the result. +// +// 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to +// OpenCOM to indicate the port number. +// +// Returns: TRUE(1): presense pulse(s) detected, device(s) reset +// FALSE(0): no presense pulses detected +// +// WARNING: Without setting the above global (FAMILY_CODE_04_ALARM_TOUCHRESET_COMPLIANCE) +// to TRUE, this routine will not function correctly on some +// Alarm reset types of the DS1994/DS1427/DS2404 with +// Rev 1,2, and 3 of the DS2480/DS2480B. +// +// +SMALLINT owTouchReset(int portnum) +{ + uchar readbuffer[10],sendpacket[10]; + uchar sendlen=0; + + if (dodebug) + printf("\nRST ");//?????????????? + + // make sure normal level + owLevel(portnum,MODE_NORMAL); + + // check if correct mode + if (UMode[portnum] != MODSEL_COMMAND) + { + UMode[portnum] = MODSEL_COMMAND; + sendpacket[sendlen++] = MODE_COMMAND; + } + + // construct the command + sendpacket[sendlen++] = (uchar)(CMD_COMM | FUNCTSEL_RESET | USpeed[portnum]); + + // flush the buffers + FlushCOM(portnum); + + // send the packet + if (WriteCOM(portnum,sendlen,sendpacket)) + { + // read back the 1 byte response + if (ReadCOM(portnum,1,readbuffer) == 1) + { + // make sure this byte looks like a reset byte + if (((readbuffer[0] & RB_RESET_MASK) == RB_PRESENCE) || + ((readbuffer[0] & RB_RESET_MASK) == RB_ALARMPRESENCE)) + { + // check if programming voltage available + ProgramAvailable[portnum] = ((readbuffer[0] & 0x20) == 0x20); + UVersion[portnum] = (readbuffer[0] & VERSION_MASK); + + // only check for alarm pulse if DS2404 present and not using THE LINK + if ((FAMILY_CODE_04_ALARM_TOUCHRESET_COMPLIANCE) && + (UVersion[portnum] != VER_LINK)) + { + msDelay(5); // delay 5 ms to give DS1994 enough time + FlushCOM(portnum); + } + return TRUE; + } + else + OWERROR(OWERROR_RESET_FAILED); + + } + else + OWERROR(OWERROR_READCOM_FAILED); + } + else + OWERROR(OWERROR_WRITECOM_FAILED); + + // an error occured so re-sync with DS2480 + DS2480Detect(portnum); + + return FALSE; +} + +//-------------------------------------------------------------------------- +// Send 1 bit of communication to the 1-Wire Net and return the +// result 1 bit read from the 1-Wire Net. The parameter 'sendbit' +// least significant bit is used and the least significant bit +// of the result is the return bit. +// +// 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to +// OpenCOM to indicate the port number. +// 'sendbit' - the least significant bit is the bit to send +// +// Returns: 0: 0 bit read from sendbit +// 1: 1 bit read from sendbit +// +SMALLINT owTouchBit(int portnum, SMALLINT sendbit) +{ + uchar readbuffer[10],sendpacket[10]; + uchar sendlen=0; + + // make sure normal level + owLevel(portnum,MODE_NORMAL); + + // check if correct mode + if (UMode[portnum] != MODSEL_COMMAND) + { + UMode[portnum] = MODSEL_COMMAND; + sendpacket[sendlen++] = MODE_COMMAND; + } + + // construct the command + sendpacket[sendlen] = (sendbit != 0) ? BITPOL_ONE : BITPOL_ZERO; + sendpacket[sendlen++] |= CMD_COMM | FUNCTSEL_BIT | USpeed[portnum]; + + // flush the buffers + FlushCOM(portnum); + + // send the packet + if (WriteCOM(portnum,sendlen,sendpacket)) + { + // read back the response + if (ReadCOM(portnum,1,readbuffer) == 1) + { + // interpret the response + if (((readbuffer[0] & 0xE0) == 0x80) && + ((readbuffer[0] & RB_BIT_MASK) == RB_BIT_ONE)) + return 1; + else + return 0; + } + else + OWERROR(OWERROR_READCOM_FAILED); + } + else + OWERROR(OWERROR_WRITECOM_FAILED); + + // an error occured so re-sync with DS2480 + DS2480Detect(portnum); + + return 0; +} + +//-------------------------------------------------------------------------- +// Send 8 bits of communication to the 1-Wire Net and verify that the +// 8 bits read from the 1-Wire Net is the same (write operation). +// The parameter 'sendbyte' least significant 8 bits are used. +// +// 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to +// OpenCOM to indicate the port number. +// 'sendbyte' - 8 bits to send (least significant byte) +// +// Returns: TRUE: bytes written and echo was the same +// FALSE: echo was not the same +// +SMALLINT owWriteByte(int portnum, SMALLINT sendbyte) +{ + return (owTouchByte(portnum,sendbyte) == (0xff & sendbyte)) ? TRUE : FALSE; +} + + +//-------------------------------------------------------------------------- +// Send 8 bits of read communication to the 1-Wire Net and and return the +// result 8 bits read from the 1-Wire Net. +// +// 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to +// OpenCOM to indicate the port number. +// +// Returns: 8 bits read from 1-Wire Net +// +SMALLINT owReadByte(int portnum) +{ + return owTouchByte(portnum,(SMALLINT)0xFF); +} + +//-------------------------------------------------------------------------- +// Send 8 bits of communication to the 1-Wire Net and return the +// result 8 bits read from the 1-Wire Net. The parameter 'sendbyte' +// least significant 8 bits are used and the least significant 8 bits +// of the result is the return byte. +// +// 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to +// OpenCOM to indicate the port number. +// 'sendbyte' - 8 bits to send (least significant byte) +// +// Returns: 8 bits read from sendbyte +// +SMALLINT owTouchByte(int portnum, SMALLINT sendbyte) +{ + uchar readbuffer[10],sendpacket[10]; + uchar sendlen=0; + + // make sure normal level + owLevel(portnum,MODE_NORMAL); + + // check if correct mode + if (UMode[portnum] != MODSEL_DATA) + { + UMode[portnum] = MODSEL_DATA; + sendpacket[sendlen++] = MODE_DATA; + } + + // add the byte to send + sendpacket[sendlen++] = (uchar)sendbyte; + + // check for duplication of data that looks like COMMAND mode + if (sendbyte ==(SMALLINT)MODE_COMMAND) + sendpacket[sendlen++] = (uchar)sendbyte; + + // flush the buffers + FlushCOM(portnum); + + // send the packet + if (WriteCOM(portnum,sendlen,sendpacket)) + { + // read back the 1 byte response + if (ReadCOM(portnum,1,readbuffer) == 1) + { + if (dodebug) + printf("%02X ",readbuffer[0]);//?????????????? + + // return the response + return (int)readbuffer[0]; + } + else + OWERROR(OWERROR_READCOM_FAILED); + } + else + OWERROR(OWERROR_WRITECOM_FAILED); + + // an error occured so re-sync with DS2480 + DS2480Detect(portnum); + + return 0; +} + +//-------------------------------------------------------------------------- +// Set the 1-Wire Net communucation speed. +// +// 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to +// OpenCOM to indicate the port number. +// 'new_speed' - new speed defined as +// MODE_NORMAL 0x00 +// MODE_OVERDRIVE 0x01 +// +// Returns: current 1-Wire Net speed +// +SMALLINT owSpeed(int portnum, SMALLINT new_speed) +{ + uchar sendpacket[5]; + uchar sendlen=0; + uchar rt = FALSE; + + // check if change from current mode + if (((new_speed == MODE_OVERDRIVE) && + (USpeed[portnum] != SPEEDSEL_OD)) || + ((new_speed == MODE_NORMAL) && + (USpeed[portnum] != SPEEDSEL_FLEX))) + { + if (new_speed == MODE_OVERDRIVE) + { + // check for unsupported mode in THE LINK + if (UVersion[portnum] == VER_LINK) + OWERROR(OWERROR_FUNC_NOT_SUP); + // if overdrive then switch to higher baud + else if (DS2480ChangeBaud(portnum,MAX_BAUD) == MAX_BAUD) + { + USpeed[portnum] = SPEEDSEL_OD; + rt = TRUE; + } + } + else if (new_speed == MODE_NORMAL) + { + // else normal so set to 9600 baud + if (DS2480ChangeBaud(portnum,PARMSET_9600) == PARMSET_9600) + { + USpeed[portnum] = SPEEDSEL_FLEX; + rt = TRUE; + } + + } + + // if baud rate is set correctly then change DS2480 speed + if (rt) + { + // check if correct mode + if (UMode[portnum] != MODSEL_COMMAND) + { + UMode[portnum] = MODSEL_COMMAND; + sendpacket[sendlen++] = MODE_COMMAND; + } + + // proceed to set the DS2480 communication speed + sendpacket[sendlen++] = CMD_COMM | FUNCTSEL_SEARCHOFF | USpeed[portnum]; + + // send the packet + if (!WriteCOM(portnum,sendlen,sendpacket)) + { + OWERROR(OWERROR_WRITECOM_FAILED); + rt = FALSE; + // lost communication with DS2480 then reset + DS2480Detect(portnum); + } + } + } + + // return the current speed + return (USpeed[portnum] == SPEEDSEL_OD) ? MODE_OVERDRIVE : MODE_NORMAL; +} + +//-------------------------------------------------------------------------- +// Set the 1-Wire Net line level. The values for new_level are +// as follows: +// +// 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to +// OpenCOM to indicate the port number. +// 'new_level' - new level defined as +// MODE_NORMAL 0x00 +// MODE_STRONG5 0x02 +// MODE_PROGRAM 0x04 +// MODE_BREAK 0x08 (not supported) +// +// Returns: current 1-Wire Net level +// +SMALLINT owLevel(int portnum, SMALLINT new_level) +{ + uchar sendpacket[10],readbuffer[10]; + uchar sendlen=0; + uchar rt=FALSE; + + // check if need to change level + if (new_level != ULevel[portnum]) + { + // check if correct mode + if (UMode[portnum] != MODSEL_COMMAND) + { + UMode[portnum] = MODSEL_COMMAND; + sendpacket[sendlen++] = MODE_COMMAND; + } + + // check if just putting back to normal + if (new_level == MODE_NORMAL) + { + // stop pulse command + sendpacket[sendlen++] = MODE_STOP_PULSE; + + // add the command to begin the pulse WITHOUT prime + sendpacket[sendlen++] = CMD_COMM | FUNCTSEL_CHMOD | SPEEDSEL_PULSE | BITPOL_5V | PRIME5V_FALSE; + + // stop pulse command + sendpacket[sendlen++] = MODE_STOP_PULSE; + + // flush the buffers + FlushCOM(portnum); + + // send the packet + if (WriteCOM(portnum,sendlen,sendpacket)) + { + // read back the 2 byte response + if (ReadCOM(portnum,2,readbuffer) == 2) + { + // check response byte + if (((readbuffer[0] & 0xE0) == 0xE0) && + ((readbuffer[1] & 0xE0) == 0xE0)) + { + rt = TRUE; + ULevel[portnum] = MODE_NORMAL; + } + } + else + OWERROR(OWERROR_READCOM_FAILED); + } + else + OWERROR(OWERROR_WRITECOM_FAILED); + } + // set new level + else + { + // strong 5 volts + if (new_level == MODE_STRONG5) + { + // set the SPUD time value + sendpacket[sendlen++] = CMD_CONFIG | PARMSEL_5VPULSE | PARMSET_infinite; + // add the command to begin the pulse + sendpacket[sendlen++] = CMD_COMM | FUNCTSEL_CHMOD | SPEEDSEL_PULSE | BITPOL_5V; + } + // 12 volts + else if (new_level == MODE_PROGRAM) + { + // check if programming voltage available + if (!ProgramAvailable[portnum]) + return MODE_NORMAL; + + // set the PPD time value + sendpacket[sendlen++] = CMD_CONFIG | PARMSEL_12VPULSE | PARMSET_infinite; + // add the command to begin the pulse + sendpacket[sendlen++] = CMD_COMM | FUNCTSEL_CHMOD | SPEEDSEL_PULSE | BITPOL_12V; + } + + // flush the buffers + FlushCOM(portnum); + + // send the packet + if (WriteCOM(portnum,sendlen,sendpacket)) + { + // read back the 1 byte response from setting time limit + if (ReadCOM(portnum,1,readbuffer) == 1) + { + // check response byte + if ((readbuffer[0] & 0x81) == 0) + { + ULevel[portnum] = new_level; + rt = TRUE; + } + } + else + OWERROR(OWERROR_READCOM_FAILED); + } + else + OWERROR(OWERROR_WRITECOM_FAILED); + } + + // if lost communication with DS2480 then reset + if (rt != TRUE) + DS2480Detect(portnum); + } + + // return the current level + return ULevel[portnum]; +} + +//-------------------------------------------------------------------------- +// This procedure creates a fixed 480 microseconds 12 volt pulse +// on the 1-Wire Net for programming EPROM iButtons. +// +// 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to +// OpenCOM to indicate the port number. +// +// Returns: TRUE successful +// FALSE program voltage not available +// +SMALLINT owProgramPulse(int portnum) +{ + uchar sendpacket[10],readbuffer[10]; + uchar sendlen=0; + + // check if programming voltage available + if (!ProgramAvailable[portnum]) + return FALSE; + + // make sure normal level + owLevel(portnum,MODE_NORMAL); + + // check if correct mode + if (UMode[portnum] != MODSEL_COMMAND) + { + UMode[portnum] = MODSEL_COMMAND; + sendpacket[sendlen++] = MODE_COMMAND; + } + + // set the SPUD time value + sendpacket[sendlen++] = CMD_CONFIG | PARMSEL_12VPULSE | PARMSET_512us; + + // pulse command + sendpacket[sendlen++] = CMD_COMM | FUNCTSEL_CHMOD | BITPOL_12V | SPEEDSEL_PULSE; + + // flush the buffers + FlushCOM(portnum); + + // send the packet + if (WriteCOM(portnum,sendlen,sendpacket)) + { + // read back the 2 byte response + if (ReadCOM(portnum,2,readbuffer) == 2) + { + // check response byte + if (((readbuffer[0] | CMD_CONFIG) == + (CMD_CONFIG | PARMSEL_12VPULSE | PARMSET_512us)) && + ((readbuffer[1] & 0xFC) == + (0xFC & (CMD_COMM | FUNCTSEL_CHMOD | BITPOL_12V | SPEEDSEL_PULSE)))) + return TRUE; + } + else + OWERROR(OWERROR_READCOM_FAILED); + } + else + OWERROR(OWERROR_WRITECOM_FAILED); + + // an error occured so re-sync with DS2480 + DS2480Detect(portnum); + + return FALSE; +} + +//-------------------------------------------------------------------------- +// Send 8 bits of communication to the 1-Wire Net and verify that the +// 8 bits read from the 1-Wire Net is the same (write operation). +// The parameter 'sendbyte' least significant 8 bits are used. After the +// 8 bits are sent change the level of the 1-Wire net. +// +// 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to +// OpenCOM to indicate the port number. +// 'sendbyte' - 8 bits to send (least significant bit) +// +// Returns: TRUE: bytes written and echo was the same, strong pullup now on +// FALSE: echo was not the same +// +SMALLINT owWriteBytePower(int portnum, SMALLINT sendbyte) +{ + uchar sendpacket[10],readbuffer[10]; + uchar sendlen=0; + uchar rt=FALSE; + uchar i, temp_byte; + + if (dodebug) + printf("P%02X ",sendbyte);//?????????????? + + // check if correct mode + if (UMode[portnum] != MODSEL_COMMAND) + { + UMode[portnum] = MODSEL_COMMAND; + sendpacket[sendlen++] = MODE_COMMAND; + } + + // set the SPUD time value + sendpacket[sendlen++] = CMD_CONFIG | PARMSEL_5VPULSE | PARMSET_infinite; + + // construct the stream to include 8 bit commands with the last one + // enabling the strong-pullup + temp_byte = sendbyte; + for (i = 0; i < 8; i++) + { + sendpacket[sendlen++] = ((temp_byte & 0x01) ? BITPOL_ONE : BITPOL_ZERO) + | CMD_COMM | FUNCTSEL_BIT | USpeed[portnum] | + ((i == 7) ? PRIME5V_TRUE : PRIME5V_FALSE); + temp_byte >>= 1; + } + + // flush the buffers + FlushCOM(portnum); + + // send the packet + if (WriteCOM(portnum,sendlen,sendpacket)) + { + // read back the 9 byte response from setting time limit + if (ReadCOM(portnum,9,readbuffer) == 9) + { + // check response + if ((readbuffer[0] & 0x81) == 0) + { + // indicate the port is now at power delivery + ULevel[portnum] = MODE_STRONG5; + + // reconstruct the echo byte + temp_byte = 0; + for (i = 0; i < 8; i++) + { + temp_byte >>= 1; + temp_byte |= (readbuffer[i + 1] & 0x01) ? 0x80 : 0; + } + + if (temp_byte == sendbyte) + rt = TRUE; + } + } + else + OWERROR(OWERROR_READCOM_FAILED); + } + else + OWERROR(OWERROR_WRITECOM_FAILED); + + // if lost communication with DS2480 then reset + if (rt != TRUE) + DS2480Detect(portnum); + + return rt; +} + +//-------------------------------------------------------------------------- +// Send 8 bits of communication to the 1-Wire Net and verify that the +// 8 bits read from the 1-Wire Net is the same (write operation). +// The parameter 'sendbyte' least significant 8 bits are used. After the +// 8 bits are sent change the level of the 1-Wire net. +// +// 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to +// OpenCOM to indicate the port number. +// 'sendbyte' - 8 bits to send (least significant bit) +// +// Returns: TRUE: bytes written and echo was the same, strong pullup now on +// FALSE: echo was not the same +// +SMALLINT owReadBytePower(int portnum) +{ + uchar sendpacket[10],readbuffer[10]; + uchar sendlen=0; + uchar rt=FALSE; + uchar i, temp_byte; + + // check if correct mode + if (UMode[portnum] != MODSEL_COMMAND) + { + UMode[portnum] = MODSEL_COMMAND; + sendpacket[sendlen++] = MODE_COMMAND; + } + + // set the SPUD time value + sendpacket[sendlen++] = CMD_CONFIG | PARMSEL_5VPULSE | PARMSET_infinite; + + // construct the stream to include 8 bit commands with the last one + // enabling the strong-pullup + temp_byte = 0xFF; + for (i = 0; i < 8; i++) + { + sendpacket[sendlen++] = ((temp_byte & 0x01) ? BITPOL_ONE : BITPOL_ZERO) + | CMD_COMM | FUNCTSEL_BIT | USpeed[portnum] | + ((i == 7) ? PRIME5V_TRUE : PRIME5V_FALSE); + temp_byte >>= 1; + } + + // flush the buffers + FlushCOM(portnum); + + // send the packet + if (WriteCOM(portnum,sendlen,sendpacket)) + { + // read back the 9 byte response from setting time limit + if (ReadCOM(portnum,9,readbuffer) == 9) + { + // check response + if ((readbuffer[0] & 0x81) == 0) + { + // indicate the port is now at power delivery + ULevel[portnum] = MODE_STRONG5; + + // reconstruct the return byte + temp_byte = 0; + for (i = 0; i < 8; i++) + { + temp_byte >>= 1; + temp_byte |= (readbuffer[i + 1] & 0x01) ? 0x80 : 0; + } + + rt = TRUE; + } + } + else + OWERROR(OWERROR_READCOM_FAILED); + } + else + OWERROR(OWERROR_WRITECOM_FAILED); + + // if lost communication with DS2480 then reset + if (rt != TRUE) + DS2480Detect(portnum); + + if (dodebug) + printf("PFF%02X ",temp_byte);//?????????????? + + return temp_byte; +} + + +//-------------------------------------------------------------------------- +// Send 1 bit of communication to the 1-Wire Net and verify that the +// response matches the 'applyPowerResponse' bit and apply power delivery +// to the 1-Wire net. Note that some implementations may apply the power +// first and then turn it off if the response is incorrect. +// +// 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to +// OpenCOM to indicate the port number. +// 'applyPowerResponse' - 1 bit response to check, if correct then start +// power delivery +// +// Returns: TRUE: bit written and response correct, strong pullup now on +// FALSE: response incorrect +// +SMALLINT owReadBitPower(int portnum, SMALLINT applyPowerResponse) +{ + uchar sendpacket[3],readbuffer[3]; + uchar sendlen=0; + uchar rt=FALSE; + + // check if correct mode + if (UMode[portnum] != MODSEL_COMMAND) + { + UMode[portnum] = MODSEL_COMMAND; + sendpacket[sendlen++] = MODE_COMMAND; + } + + // set the SPUD time value + sendpacket[sendlen++] = CMD_CONFIG | PARMSEL_5VPULSE | PARMSET_infinite; + + // enabling the strong-pullup after bit + sendpacket[sendlen++] = BITPOL_ONE + | CMD_COMM | FUNCTSEL_BIT | USpeed[portnum] | + PRIME5V_TRUE; + // flush the buffers + FlushCOM(portnum); + + // send the packet + if (WriteCOM(portnum,sendlen,sendpacket)) + { + // read back the 2 byte response from setting time limit + if (ReadCOM(portnum,2,readbuffer) == 2) + { + // check response to duration set + if ((readbuffer[0] & 0x81) == 0) + { + // indicate the port is now at power delivery + ULevel[portnum] = MODE_STRONG5; + + // check the response bit + if ((readbuffer[1] & 0x01) == applyPowerResponse) + rt = TRUE; + else + owLevel(portnum,MODE_NORMAL); + + return rt; + } + } + else + OWERROR(OWERROR_READCOM_FAILED); + } + else + OWERROR(OWERROR_WRITECOM_FAILED); + + // if lost communication with DS2480 then reset + if (rt != TRUE) + DS2480Detect(portnum); + + return rt; +} + +//-------------------------------------------------------------------------- +// This procedure indicates whether the adapter can deliver power. +// +// 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to +// OpenCOM to indicate the port number. +// +// Returns: TRUE because all userial adapters have over drive. +// +SMALLINT owHasPowerDelivery(int portnum) +{ + return TRUE; +} + +//-------------------------------------------------------------------------- +// This procedure indicates wether the adapter can deliver power. +// +// 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to +// OpenCOM to indicate the port number. +// +// Returns: TRUE because all userial adapters have over drive. +// +SMALLINT owHasOverDrive(int portnum) +{ + return TRUE; +} +//-------------------------------------------------------------------------- +// This procedure creates a fixed 480 microseconds 12 volt pulse +// on the 1-Wire Net for programming EPROM iButtons. +// +// 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to +// OpenCOM to indicate the port number. +// +// Returns: TRUE program volatage available +// FALSE program voltage not available +SMALLINT owHasProgramPulse(int portnum) +{ + return ProgramAvailable[portnum]; +} diff --git a/src/plugins/pro1_data_zip/ow/ownet.h b/src/plugins/pro1_data_zip/ow/ownet.h new file mode 100644 index 0000000..d163577 --- /dev/null +++ b/src/plugins/pro1_data_zip/ow/ownet.h @@ -0,0 +1,440 @@ +/*--------------------------------------------------------------------------- + * Copyright (C) 2000 Dallas Semiconductor Corporation, All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL DALLAS SEMICONDUCTOR BE LIABLE FOR ANY CLAIM, DAMAGES + * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of Dallas Semiconductor + * shall not be used except as stated in the Dallas Semiconductor + * Branding Policy. + *--------------------------------------------------------------------------- + * + * ownet.h - Include file for 1-Wire Net library + * + * Version: 2.10 + * + * History: 1.02 -> 1.03 Make sure uchar is not defined twice. + * 1.03 -> 2.00 Changed 'MLan' to 'ow'. + * 2.00 -> 2.01 Added error handling. Added circular-include check. + * 2.01 -> 2.10 Added raw memory error handling and SMALLINT + * 2.10 -> 3.00 Added memory bank functionality + * Added file I/O operations + */ + +#ifndef OWNET_H +#define OWNET_H + +/* Vyhd note: if I'm ever adventurous enough, I'll fix this up and manually + * get rid of the warnings. Until then, there's #pragma warning. */ + +#ifdef _MSC_VER +#pragma warning (disable : 4100) /* unreferenced formal parameter */ +#pragma warning (disable : 4244) /* conversion from blah to blah, possible loss of data */ +#pragma warning (disable : 4701) /* local variable may be used without having been initialized */ +#endif + +/*-------------------------------------------------------------* + * Common Includes to ownet applications * + *-------------------------------------------------------------*/ +#include + +/* Workaround for Windows compilation. + * The below doesn't actually work. :/ + */ +typedef unsigned short ushort; +typedef unsigned long ulong; + +/*-------------------------------------------------------------* + * Target Specific Information * + *-------------------------------------------------------------*/ + +/*-------------------------------------------------------------* + * Handhelds (PalmOS, WinCE) * + *-------------------------------------------------------------*/ +#ifdef __MC68K__ + /* MC68K is the type of processor in the PILOT + * Metrowerk's CodeWarrior defines this symbol + */ + #include + #ifndef strcmp + #include + #define strcmp StrCompare + #endif + #include +#endif + +#ifdef _WIN32_WCE + /* All of our projects had this flag defined by default (_WIN32_WCE), + * but I'm not 100% positive that this is _the_ definitive + * flag to use to identify a WinCE system. + */ + #include "WinCElnk.h" + #ifndef FILE + #define FILE int + extern int sprintf(char *buffer, char *format,...); + extern void fprintf(FILE *fp, char *format,...); + extern void printf(char *format,...); + #endif +#endif + +#if !defined(_WIN32_WCE) && !defined(__MC68K__) + #include +#endif + +#ifdef __C51__ + #define FILE int + #define exit(c) return + typedef unsigned int ushort; + typedef unsigned long ulong; + #define SMALLINT uchar +#endif + +#ifdef __ICCMAXQ__ + #define FILE int + #define stdout 0 + #define stdin 1 + #define stderr 2 + typedef unsigned int ushort; + typedef unsigned long ulong; + #define SMALLINT short + #define main micro_main + #define real_main main + #define SMALL_MEMORY_TARGET +#endif + + +/*--------------------------------------------------------------* + * Typedefs * + *--------------------------------------------------------------*/ +#ifndef SMALLINT + /* purpose of smallint is for compile-time changing of formal + * parameters and return values of functions. For each target + * machine, an integer is alleged to represent the most "simple" + * number representable by that architecture. This should, in + * most cases, produce optimal code for that particular arch. + * BUT... The majority of compilers designed for embedded + * processors actually keep an int at 16 bits, although the + * architecture might only be comfortable with 8 bits. + * The default size of smallint will be the same as that of + * an integer, but this allows for easy overriding of that size. + * + * NOTE: + * In all cases where a smallint is used, it is assumed that + * decreasing the size of this integer to something as low as + * a single byte _will_not_ change the functionality of the + * application. e.g. a loop counter that will iterate through + * several kilobytes of data should not be SMALLINT. The most + * common place you'll see smallint is for boolean return types. + */ + #define SMALLINT int +#endif + +/* setting max baud */ +#ifdef _WINDOWS + /* 0x02 = PARAMSET_19200 */ +#define MAX_BAUD 0x02 +#else + /* 0x06 = PARMSET_115200 */ +#define MAX_BAUD 0x06 +#endif + +#ifndef OW_UCHAR + #define OW_UCHAR + typedef unsigned char uchar; + #if !defined(__MINGW32__) && (defined(__CYGWIN__) || defined(__GNUC__)) + typedef unsigned long ulong; + /* ushort already defined in sys/types.h */ + #include + #else + #if defined(_WIN32) || defined(WIN32) || defined(__MC68K__) || defined(_WIN32_WCE) || defined(_DOS) || defined(_WINDOWS) || defined(__MINGW32__) + typedef unsigned short ushort; + typedef unsigned long ulong; + #endif + #endif + #ifdef __sun__ + #include + #endif + #ifdef SDCC + /* intent of ushort is 2 bytes unsigned. + * for ds390 in sdcc, an int, not a short, + * is 2 bytes. + */ + typedef unsigned int ushort; + #endif +#endif + +/* general defines */ +#define WRITE_FUNCTION 1 +#define READ_FUNCTION 0 + +/* error codes + * todo: investigate these and replace with new Error Handling library + */ +#define READ_ERROR -1 +#define INVALID_DIR -2 +#define NO_FILE -3 +#define WRITE_ERROR -4 +#define WRONG_TYPE -5 +#define FILE_TOO_BIG -6 + +/* Misc */ +#define FALSE 0 +#define TRUE 1 + +#ifndef MAX_PORTNUM + #define MAX_PORTNUM 16 +#endif + +/* mode bit flags */ +#define MODE_NORMAL 0x00 +#define MODE_OVERDRIVE 0x01 +#define MODE_STRONG5 0x02 +#define MODE_PROGRAM 0x04 +#define MODE_BREAK 0x08 + +/* Output flags */ +#define LV_ALWAYS 2 +#define LV_OPTIONAL 1 +#define LV_VERBOSE 0 + +/*--------------------------------------------------------------* + * Error handling * + *--------------------------------------------------------------*/ +extern int owGetErrorNum(void); +extern int owHasErrors(void); + +/* Clears the stack. */ +#define OWERROR_CLEAR() while(owHasErrors()) owGetErrorNum(); + +#ifdef DEBUG + /* Raises an exception with extra debug info */ + #define OWERROR(err) owRaiseError(err,__LINE__,__FILE__) + extern void owRaiseError(int,int,char*); + #define OWASSERT(s,err,ret) if(!(s)){owRaiseError((err),__LINE__,__FILE__);return (ret);} +#else + /* Raises an exception with just the error code */ + #define OWERROR(err) owRaiseError(err) + extern void owRaiseError(int); + #define OWASSERT(s,err,ret) if(!(s)){owRaiseError((err));return (ret);} +#endif + +#ifdef SMALL_MEMORY_TARGET + #define OWERROR_DUMP(fileno) /*no-op*/; +#else + /* Prints the stack out to the given file. */ + #define OWERROR_DUMP(fileno) while(owHasErrors()) owPrintErrorMsg(fileno); + extern void owPrintErrorMsg(FILE *); + extern void owPrintErrorMsgStd(); + extern char *owGetErrorMsg(int); +#endif + +#define OWERROR_NO_ERROR_SET 0 +#define OWERROR_NO_DEVICES_ON_NET 1 +#define OWERROR_RESET_FAILED 2 +#define OWERROR_SEARCH_ERROR 3 +#define OWERROR_ACCESS_FAILED 4 +#define OWERROR_DS2480_NOT_DETECTED 5 +#define OWERROR_DS2480_WRONG_BAUD 6 +#define OWERROR_DS2480_BAD_RESPONSE 7 +#define OWERROR_OPENCOM_FAILED 8 +#define OWERROR_WRITECOM_FAILED 9 +#define OWERROR_READCOM_FAILED 10 +#define OWERROR_BLOCK_TOO_BIG 11 +#define OWERROR_BLOCK_FAILED 12 +#define OWERROR_PROGRAM_PULSE_FAILED 13 +#define OWERROR_PROGRAM_BYTE_FAILED 14 +#define OWERROR_WRITE_BYTE_FAILED 15 +#define OWERROR_READ_BYTE_FAILED 16 +#define OWERROR_WRITE_VERIFY_FAILED 17 +#define OWERROR_READ_VERIFY_FAILED 18 +#define OWERROR_WRITE_SCRATCHPAD_FAILED 19 +#define OWERROR_COPY_SCRATCHPAD_FAILED 20 +#define OWERROR_INCORRECT_CRC_LENGTH 21 +#define OWERROR_CRC_FAILED 22 +#define OWERROR_GET_SYSTEM_RESOURCE_FAILED 23 +#define OWERROR_SYSTEM_RESOURCE_INIT_FAILED 24 +#define OWERROR_DATA_TOO_LONG 25 +#define OWERROR_READ_OUT_OF_RANGE 26 +#define OWERROR_WRITE_OUT_OF_RANGE 27 +#define OWERROR_DEVICE_SELECT_FAIL 28 +#define OWERROR_READ_SCRATCHPAD_VERIFY 29 +#define OWERROR_COPY_SCRATCHPAD_NOT_FOUND 30 +#define OWERROR_ERASE_SCRATCHPAD_NOT_FOUND 31 +#define OWERROR_ADDRESS_READ_BACK_FAILED 32 +#define OWERROR_EXTRA_INFO_NOT_SUPPORTED 33 +#define OWERROR_PG_PACKET_WITHOUT_EXTRA 34 +#define OWERROR_PACKET_LENGTH_EXCEEDS_PAGE 35 +#define OWERROR_INVALID_PACKET_LENGTH 36 +#define OWERROR_NO_PROGRAM_PULSE 37 +#define OWERROR_READ_ONLY 38 +#define OWERROR_NOT_GENERAL_PURPOSE 39 +#define OWERROR_READ_BACK_INCORRECT 40 +#define OWERROR_INVALID_PAGE_NUMBER 41 +#define OWERROR_CRC_NOT_SUPPORTED 42 +#define OWERROR_CRC_EXTRA_INFO_NOT_SUPPORTED 43 +#define OWERROR_READ_BACK_NOT_VALID 44 +#define OWERROR_COULD_NOT_LOCK_REDIRECT 45 +#define OWERROR_READ_STATUS_NOT_COMPLETE 46 +#define OWERROR_PAGE_REDIRECTION_NOT_SUPPORTED 47 +#define OWERROR_LOCK_REDIRECTION_NOT_SUPPORTED 48 +#define OWERROR_READBACK_EPROM_FAILED 49 +#define OWERROR_PAGE_LOCKED 50 +#define OWERROR_LOCKING_REDIRECTED_PAGE_AGAIN 51 +#define OWERROR_REDIRECTED_PAGE 52 +#define OWERROR_PAGE_ALREADY_LOCKED 53 +#define OWERROR_WRITE_PROTECTED 54 +#define OWERROR_NONMATCHING_MAC 55 +#define OWERROR_WRITE_PROTECT 56 +#define OWERROR_WRITE_PROTECT_SECRET 57 +#define OWERROR_COMPUTE_NEXT_SECRET 58 +#define OWERROR_LOAD_FIRST_SECRET 59 +#define OWERROR_POWER_NOT_AVAILABLE 60 +#define OWERROR_XBAD_FILENAME 61 +#define OWERROR_XUNABLE_TO_CREATE_DIR 62 +#define OWERROR_REPEAT_FILE 63 +#define OWERROR_DIRECTORY_NOT_EMPTY 64 +#define OWERROR_WRONG_TYPE 65 +#define OWERROR_BUFFER_TOO_SMALL 66 +#define OWERROR_NOT_WRITE_ONCE 67 +#define OWERROR_FILE_NOT_FOUND 68 +#define OWERROR_OUT_OF_SPACE 69 +#define OWERROR_TOO_LARGE_BITNUM 70 +#define OWERROR_NO_PROGRAM_JOB 71 +#define OWERROR_FUNC_NOT_SUP 72 +#define OWERROR_HANDLE_NOT_USED 73 +#define OWERROR_FILE_WRITE_ONLY 74 +#define OWERROR_HANDLE_NOT_AVAIL 75 +#define OWERROR_INVALID_DIRECTORY 76 +#define OWERROR_HANDLE_NOT_EXIST 77 +#define OWERROR_NONMATCHING_SNUM 78 +#define OWERROR_NON_PROGRAM_PARTS 79 +#define OWERROR_PROGRAM_WRITE_PROTECT 80 +#define OWERROR_FILE_READ_ERR 81 +#define OWERROR_ADDFILE_TERMINATED 82 +#define OWERROR_READ_MEMORY_PAGE_FAILED 83 +#define OWERROR_MATCH_SCRATCHPAD_FAILED 84 +#define OWERROR_ERASE_SCRATCHPAD_FAILED 85 +#define OWERROR_READ_SCRATCHPAD_FAILED 86 +#define OWERROR_SHA_FUNCTION_FAILED 87 +#define OWERROR_NO_COMPLETION_BYTE 88 +#define OWERROR_WRITE_DATA_PAGE_FAILED 89 +#define OWERROR_COPY_SECRET_FAILED 90 +#define OWERROR_BIND_SECRET_FAILED 91 +#define OWERROR_INSTALL_SECRET_FAILED 92 +#define OWERROR_VERIFY_SIG_FAILED 93 +#define OWERROR_SIGN_SERVICE_DATA_FAILED 94 +#define OWERROR_VERIFY_AUTH_RESPONSE_FAILED 95 +#define OWERROR_ANSWER_CHALLENGE_FAILED 96 +#define OWERROR_CREATE_CHALLENGE_FAILED 97 +#define OWERROR_BAD_SERVICE_DATA 98 +#define OWERROR_SERVICE_DATA_NOT_UPDATED 99 +#define OWERROR_CATASTROPHIC_SERVICE_FAILURE 100 +#define OWERROR_LOAD_FIRST_SECRET_FAILED 101 +#define OWERROR_MATCH_SERVICE_SIGNATURE_FAILED 102 +#define OWERROR_KEY_OUT_OF_RANGE 103 +#define OWERROR_BLOCK_ID_OUT_OF_RANGE 104 +#define OWERROR_PASSWORDS_ENABLED 105 +#define OWERROR_PASSWORD_INVALID 106 +#define OWERROR_NO_READ_ONLY_PASSWORD 107 +#define OWERROR_NO_READ_WRITE_PASSWORD 108 +#define OWERROR_OW_SHORTED 109 +#define OWERROR_ADAPTER_ERROR 110 +#define OWERROR_EOP_COPY_SCRATCHPAD_FAILED 111 +#define OWERROR_EOP_WRITE_SCRATCHPAD_FAILED 112 +#define OWERROR_HYGRO_STOP_MISSION_UNNECESSARY 113 +#define OWERROR_HYGRO_STOP_MISSION_ERROR 114 +#define OWERROR_PORTNUM_ERROR 115 +#define OWERROR_LEVEL_FAILED 116 +#define OWERROR_PASSWORD_NOT_SET 117 +#define OWERROR_LATCH_NOT_SET 118 +#define OWERROR_LIBUSB_OPEN_FAILED 119 +#define OWERROR_LIBUSB_DEVICE_ALREADY_OPENED 120 +#define OWERROR_LIBUSB_SET_CONFIGURATION_ERROR 121 +#define OWERROR_LIBUSB_CLAIM_INTERFACE_ERROR 122 +#define OWERROR_LIBUSB_SET_ALTINTERFACE_ERROR 123 +#define OWERROR_LIBUSB_NO_ADAPTER_FOUND 124 + +/* One Wire functions defined in ownetu.c */ +SMALLINT owFirst(int portnum, SMALLINT do_reset, SMALLINT alarm_only); +SMALLINT owNext(int portnum, SMALLINT do_reset, SMALLINT alarm_only); +void owSerialNum(int portnum, uchar *serialnum_buf, SMALLINT do_read); +void owFamilySearchSetup(int portnum, SMALLINT search_family); +void owSkipFamily(int portnum); +SMALLINT owAccess(int portnum); +SMALLINT owVerify(int portnum, SMALLINT alarm_only); +SMALLINT owOverdriveAccess(int portnum); + + +/* external One Wire functions defined in owsesu.c */ + SMALLINT owAcquire(int portnum, char *port_zstr); + int owAcquireEx(const char *port_zstr); + void owRelease(int portnum); + +/* external One Wire functions defined in findtype.c */ +/* SMALLINT FindDevices(int,uchar FamilySN[][8],SMALLINT,int); */ + +/* external One Wire functions from link layer owllu.c */ +SMALLINT owTouchReset(int portnum); +SMALLINT owTouchBit(int portnum, SMALLINT sendbit); +SMALLINT owTouchByte(int portnum, SMALLINT sendbyte); +SMALLINT owWriteByte(int portnum, SMALLINT sendbyte); +SMALLINT owReadByte(int portnum); +SMALLINT owSpeed(int portnum, SMALLINT new_speed); +SMALLINT owLevel(int portnum, SMALLINT new_level); +SMALLINT owProgramPulse(int portnum); +SMALLINT owWriteBytePower(int portnum, SMALLINT sendbyte); +SMALLINT owReadBytePower(int portnum); +SMALLINT owHasPowerDelivery(int portnum); +SMALLINT owHasProgramPulse(int portnum); +SMALLINT owHasOverDrive(int portnum); +SMALLINT owReadBitPower(int portnum, SMALLINT applyPowerResponse); +/* external One Wire global from owllu.c */ +extern SMALLINT FAMILY_CODE_04_ALARM_TOUCHRESET_COMPLIANCE; + +/* external One Wire functions from transaction layer in owtrnu.c */ +SMALLINT owBlock(int portnum, SMALLINT do_reset, uchar *tran_buf, SMALLINT tran_len); +SMALLINT owReadPacketStd(int portnum, SMALLINT do_access, int start_page, uchar *read_buf); +SMALLINT owWritePacketStd(int portnum, int start_page, uchar *write_buf, + SMALLINT write_len, SMALLINT is_eprom, SMALLINT crc_type); +SMALLINT owProgramByte(int portnum, SMALLINT write_byte, int addr, SMALLINT write_cmd, + SMALLINT crc_type, SMALLINT do_access); + +/* link functions */ +void msDelay(int len); +long msGettick(void); + +/* ioutil.c functions prototypes */ +int EnterString(char *msg, char *buf, int min, int max); +int EnterNum(char *msg, int numchars, long *value, long min, long max); +int EnterHex(char *msg, int numchars, ulong *value); +int ToHex(char ch); +int getkeystroke(void); +int key_abort(void); +void ExitProg(char *msg, int exit_code); +int getData(uchar *write_buff, int max_len, SMALLINT gethex); +void PrintHex(uchar* buffer, int cnt); +void PrintChars(uchar* buffer, int cnt); +void PrintSerialNum(uchar* buffer); + +/* external functions defined in crcutil.c */ +void setcrc16(int portnum, ushort reset); +ushort docrc16(int portnum, ushort cdata); +void setcrc8(int portnum, uchar reset); +uchar docrc8(int portnum, uchar x); + +#endif /* OWNET_H */ diff --git a/src/plugins/pro1_data_zip/ow/ownetu.c b/src/plugins/pro1_data_zip/ow/ownetu.c new file mode 100644 index 0000000..598a044 --- /dev/null +++ b/src/plugins/pro1_data_zip/ow/ownetu.c @@ -0,0 +1,597 @@ +//--------------------------------------------------------------------------- +// Copyright (C) 2000 Dallas Semiconductor Corporation, All Rights Reserved. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL DALLAS SEMICONDUCTOR BE LIABLE FOR ANY CLAIM, DAMAGES +// OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// +// Except as contained in this notice, the name of Dallas Semiconductor +// shall not be used except as stated in the Dallas Semiconductor +// Branding Policy. +//--------------------------------------------------------------------------- +// +// owNetU.C - Network functions for 1-Wire Net devices +// using the DS2480/DS2480B (U) serial interface chip. +// +// Version: 2.01 +// +// 1.02 -> 1.03 Removed caps in #includes for Linux capatibility +// 1.03 -> 2.00 Changed 'MLan' to 'ow'. Added support for +// multiple ports. +// 2.00 -> 2.01 Added error handling. Added circular-include check. +// 2.01 -> 2.10 Added raw memory error handling and SMALLINT +// 2.10 -> 3.00 Added memory bank functionality +// Added file I/O operations +// Updated search functions to be consistent with AN192 +// + +#include "ownet.h" +#include "ds2480.h" + +// local functions defined in ownetu.c +static SMALLINT bitacc(SMALLINT,SMALLINT,SMALLINT,uchar *); + +// global variables for this module to hold search state information +static int LastDiscrepancy[MAX_PORTNUM]; +static int LastFamilyDiscrepancy[MAX_PORTNUM]; +static uchar LastDevice[MAX_PORTNUM]; +uchar SerialNum[MAX_PORTNUM][8]; + +// external globals +extern int UMode[MAX_PORTNUM]; +extern uchar USpeed[MAX_PORTNUM]; + +//-------------------------------------------------------------------------- +// The 'owFirst' finds the first device on the 1-Wire Net This function +// contains one parameter 'alarm_only'. When +// 'alarm_only' is TRUE (1) the find alarm command 0xEC is +// sent instead of the normal search command 0xF0. +// Using the find alarm command 0xEC will limit the search to only +// 1-Wire devices that are in an 'alarm' state. +// +// 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to +// indicate the symbolic port number. +// 'do_reset' - TRUE (1) perform reset before search, FALSE (0) do not +// perform reset before search. +// 'alarm_only' - TRUE (1) the find alarm command 0xEC is +// sent instead of the normal search command 0xF0 +// +// Returns: TRUE (1) : when a 1-Wire device was found and it's +// Serial Number placed in the global SerialNum +// FALSE (0): There are no devices on the 1-Wire Net. +// +SMALLINT owFirst(int portnum, SMALLINT do_reset, SMALLINT alarm_only) +{ + // reset the search state + LastDiscrepancy[portnum] = 0; + LastDevice[portnum] = FALSE; + LastFamilyDiscrepancy[portnum] = 0; + + return owNext(portnum, do_reset, alarm_only); +} + +//-------------------------------------------------------------------------- +// The 'owNext' function does a general search. This function +// continues from the previos search state. The search state +// can be reset by using the 'owFirst' function. +// This function contains one parameter 'alarm_only'. +// When 'alarm_only' is TRUE (1) the find alarm command +// 0xEC is sent instead of the normal search command 0xF0. +// Using the find alarm command 0xEC will limit the search to only +// 1-Wire devices that are in an 'alarm' state. +// +// 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to +// OpenCOM to indicate the port number. +// 'do_reset' - TRUE (1) perform reset before search, FALSE (0) do not +// perform reset before search. +// 'alarm_only' - TRUE (1) the find alarm command 0xEC is +// sent instead of the normal search command 0xF0 +// +// Returns: TRUE (1) : when a 1-Wire device was found and it's +// Serial Number placed in the global SerialNum +// FALSE (0): when no new device was found. Either the +// last search was the last device or there +// are no devices on the 1-Wire Net. +// +SMALLINT owNext(int portnum, SMALLINT do_reset, SMALLINT alarm_only) +{ + uchar last_zero,pos; + uchar tmp_serial_num[8]; + uchar readbuffer[20],sendpacket[40]; + uchar i,sendlen=0; + uchar lastcrc8; + + // if the last call was the last one + if (LastDevice[portnum]) + { + // reset the search + LastDiscrepancy[portnum] = 0; + LastDevice[portnum] = FALSE; + LastFamilyDiscrepancy[portnum] = 0; + return FALSE; + } + + // check if reset first is requested + if (do_reset) + { + // reset the 1-wire + // if there are no parts on 1-wire, return FALSE + if (!owTouchReset(portnum)) + { + // reset the search + LastDiscrepancy[portnum] = 0; + LastFamilyDiscrepancy[portnum] = 0; + OWERROR(OWERROR_NO_DEVICES_ON_NET); + return FALSE; + } + } + + // build the command stream + // call a function that may add the change mode command to the buff + // check if correct mode + if (UMode[portnum] != MODSEL_DATA) + { + UMode[portnum] = MODSEL_DATA; + sendpacket[sendlen++] = MODE_DATA; + } + + // search command + if (alarm_only) + sendpacket[sendlen++] = 0xEC; // issue the alarming search command + else + sendpacket[sendlen++] = 0xF0; // issue the search command + + // change back to command mode + UMode[portnum] = MODSEL_COMMAND; + sendpacket[sendlen++] = MODE_COMMAND; + + // search mode on + sendpacket[sendlen++] = (uchar)(CMD_COMM | FUNCTSEL_SEARCHON | USpeed[portnum]); + + // change back to data mode + UMode[portnum] = MODSEL_DATA; + sendpacket[sendlen++] = MODE_DATA; + + // set the temp Last Descrep to none + last_zero = 0; + + // add the 16 bytes of the search + pos = sendlen; + for (i = 0; i < 16; i++) + sendpacket[sendlen++] = 0; + + // only modify bits if not the first search + if (LastDiscrepancy[portnum] != 0) + { + // set the bits in the added buffer + for (i = 0; i < 64; i++) + { + // before last discrepancy + if (i < (LastDiscrepancy[portnum] - 1)) + bitacc(WRITE_FUNCTION, + bitacc(READ_FUNCTION,0,i,&SerialNum[portnum][0]), + (short)(i * 2 + 1), + &sendpacket[pos]); + // at last discrepancy + else if (i == (LastDiscrepancy[portnum] - 1)) + bitacc(WRITE_FUNCTION,1, + (short)(i * 2 + 1), + &sendpacket[pos]); + // after last discrepancy so leave zeros + } + } + + // change back to command mode + UMode[portnum] = MODSEL_COMMAND; + sendpacket[sendlen++] = MODE_COMMAND; + + // search OFF + sendpacket[sendlen++] = (uchar)(CMD_COMM | FUNCTSEL_SEARCHOFF | USpeed[portnum]); + + // flush the buffers + FlushCOM(portnum); + + // send the packet + if (WriteCOM(portnum,sendlen,sendpacket)) + { + // read back the 1 byte response + if (ReadCOM(portnum,17,readbuffer) == 17) + { + // interpret the bit stream + for (i = 0; i < 64; i++) + { + // get the SerialNum bit + bitacc(WRITE_FUNCTION, + bitacc(READ_FUNCTION,0,(short)(i * 2 + 1),&readbuffer[1]), + i, + &tmp_serial_num[0]); + // check LastDiscrepancy + if ((bitacc(READ_FUNCTION,0,(short)(i * 2),&readbuffer[1]) == 1) && + (bitacc(READ_FUNCTION,0,(short)(i * 2 + 1),&readbuffer[1]) == 0)) + { + last_zero = i + 1; + // check LastFamilyDiscrepancy + if (i < 8) + LastFamilyDiscrepancy[portnum] = i + 1; + } + } + + // do dowcrc + setcrc8(portnum,0); +// for (i = 0; i < 8; i++) +// lastcrc8 = docrc8(portnum,tmp_serial_num[i]); + // The above has been commented out for the DS28E04. The + // below has been added to accomidate the valid CRC with the + // possible changing serial number values of the DS28E04. + for (i = 0; i < 8; i++) + { + if (((tmp_serial_num[0] & 0x7F) == 0x1C) && (i == 1)) + lastcrc8 = docrc8(portnum,0x7F); + else + lastcrc8 = docrc8(portnum,tmp_serial_num[i]); + } + + + // check results + if ((lastcrc8 != 0) || (LastDiscrepancy[portnum] == 63) || (tmp_serial_num[0] == 0)) + { + // error during search + // reset the search + LastDiscrepancy[portnum] = 0; + LastDevice[portnum] = FALSE; + LastFamilyDiscrepancy[portnum] = 0; + OWERROR(OWERROR_SEARCH_ERROR); + return FALSE; + } + // successful search + else + { + // set the last discrepancy + LastDiscrepancy[portnum] = last_zero; + + // check for last device + if (LastDiscrepancy[portnum] == 0) + LastDevice[portnum] = TRUE; + + // copy the SerialNum to the buffer + for (i = 0; i < 8; i++) + SerialNum[portnum][i] = tmp_serial_num[i]; + + // set the count + return TRUE; + } + } + else + OWERROR(OWERROR_READCOM_FAILED); + } + else + OWERROR(OWERROR_WRITECOM_FAILED); + + // an error occured so re-sync with DS2480 + DS2480Detect(portnum); + + // reset the search + LastDiscrepancy[portnum] = 0; + LastDevice[portnum] = FALSE; + LastFamilyDiscrepancy[portnum] = 0; + + return FALSE; +} + +//-------------------------------------------------------------------------- +// The 'owSerialNum' function either reads or sets the SerialNum buffer +// that is used in the search functions 'owFirst' and 'owNext'. +// This function contains two parameters, 'serialnum_buf' is a pointer +// to a buffer provided by the caller. 'serialnum_buf' should point to +// an array of 8 unsigned chars. The second parameter is a flag called +// 'do_read' that is TRUE (1) if the operation is to read and FALSE +// (0) if the operation is to set the internal SerialNum buffer from +// the data in the provided buffer. +// +// 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to +// OpenCOM to indicate the port number. +// 'serialnum_buf' - buffer to that contains the serial number to set +// when do_read = FALSE (0) and buffer to get the serial +// number when do_read = TRUE (1). +// 'do_read' - flag to indicate reading (1) or setting (0) the current +// serial number. +// +void owSerialNum(int portnum, uchar *serialnum_buf, SMALLINT do_read) +{ + uchar i; + + // read the internal buffer and place in 'serialnum_buf' + if (do_read) + { + for (i = 0; i < 8; i++) + serialnum_buf[i] = SerialNum[portnum][i]; + } + // set the internal buffer from the data in 'serialnum_buf' + else + { + for (i = 0; i < 8; i++) + SerialNum[portnum][i] = serialnum_buf[i]; + } +} + +//-------------------------------------------------------------------------- +// Setup the search algorithm to find a certain family of devices +// the next time a search function is called 'owNext'. +// +// 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to +// OpenCOM to indicate the port number. +// 'search_family' - family code type to set the search algorithm to find +// next. +// +void owFamilySearchSetup(int portnum, SMALLINT search_family) +{ + uchar i; + + // set the search state to find search_family type devices + SerialNum[portnum][0] = search_family; + for (i = 1; i < 8; i++) + SerialNum[portnum][i] = 0; + LastDiscrepancy[portnum] = 64; + LastFamilyDiscrepancy[portnum] = 0; + LastDevice[portnum] = FALSE; +} + +//-------------------------------------------------------------------------- +// Set the current search state to skip the current family code. +// +// 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to +// OpenCOM to indicate the port number. +// +void owSkipFamily(int portnum) +{ + // set the Last discrepancy to last family discrepancy + LastDiscrepancy[portnum] = LastFamilyDiscrepancy[portnum]; + + // clear the last family discrpepancy + LastFamilyDiscrepancy[portnum] = 0; + + // check for end of list + if (LastDiscrepancy[portnum] == 0) + LastDevice[portnum] = TRUE; +} + +//-------------------------------------------------------------------------- +// The 'owAccess' function resets the 1-Wire and sends a MATCH Serial +// Number command followed by the current SerialNum code. After this +// function is complete the 1-Wire device is ready to accept device-specific +// commands. +// +// 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to +// OpenCOM to indicate the port number. +// +// Returns: TRUE (1) : reset indicates present and device is ready +// for commands. +// FALSE (0): reset does not indicate presence or echos 'writes' +// are not correct. +// +SMALLINT owAccess(int portnum) +{ + uchar sendpacket[9]; + uchar i; + + // reset the 1-wire + if (owTouchReset(portnum)) + { + // create a buffer to use with block function + // match Serial Number command 0x55 + sendpacket[0] = 0x55; + // Serial Number + for (i = 1; i < 9; i++) + sendpacket[i] = SerialNum[portnum][i-1]; + + // send/recieve the transfer buffer + if (owBlock(portnum,FALSE,sendpacket,9)) + { + // verify that the echo of the writes was correct + for (i = 1; i < 9; i++) + if (sendpacket[i] != SerialNum[portnum][i-1]) + return FALSE; + + if (sendpacket[0] != 0x55) + { + OWERROR(OWERROR_WRITE_VERIFY_FAILED); + return FALSE; + } + else + return TRUE; + } + else + OWERROR(OWERROR_BLOCK_FAILED); + } + else + OWERROR(OWERROR_NO_DEVICES_ON_NET); + + // reset or match echo failed + return FALSE; +} + +//---------------------------------------------------------------------- +// The function 'owVerify' verifies that the current device +// is in contact with the 1-Wire Net. +// Using the find alarm command 0xEC will verify that the device +// is in contact with the 1-Wire Net and is in an 'alarm' state. +// +// 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to +// OpenCOM to indicate the port number. +// 'alarm_only' - TRUE (1) the find alarm command 0xEC +// is sent instead of the normal search +// command 0xF0. +// +// Returns: TRUE (1) : when the 1-Wire device was verified +// to be on the 1-Wire Net +// with alarm_only == FALSE +// or verified to be on the 1-Wire Net +// AND in an alarm state when +// alarm_only == TRUE. +// FALSE (0): the 1-Wire device was not on the +// 1-Wire Net or if alarm_only +// == TRUE, the device may be on the +// 1-Wire Net but in a non-alarm state. +// +SMALLINT owVerify(int portnum, SMALLINT alarm_only) +{ + uchar i,sendlen=0,goodbits=0,cnt=0,s,tst; + uchar sendpacket[50]; + + // construct the search rom + if (alarm_only) + sendpacket[sendlen++] = 0xEC; // issue the alarming search command + else + sendpacket[sendlen++] = 0xF0; // issue the search command + // set all bits at first + for (i = 1; i <= 24; i++) + sendpacket[sendlen++] = 0xFF; + // now set or clear apropriate bits for search + for (i = 0; i < 64; i++) + bitacc(WRITE_FUNCTION,bitacc(READ_FUNCTION,0,i,&SerialNum[portnum][0]),(int)((i+1)*3-1),&sendpacket[1]); + + // send/recieve the transfer buffer + if (owBlock(portnum,TRUE,sendpacket,sendlen)) + { + // check results to see if it was a success + for (i = 0; i < 192; i += 3) + { + tst = (bitacc(READ_FUNCTION,0,i,&sendpacket[1]) << 1) | + bitacc(READ_FUNCTION,0,(int)(i+1),&sendpacket[1]); + + s = bitacc(READ_FUNCTION,0,cnt++,&SerialNum[portnum][0]); + + if (tst == 0x03) // no device on line + { + goodbits = 0; // number of good bits set to zero + break; // quit + } + + if (((s == 0x01) && (tst == 0x02)) || + ((s == 0x00) && (tst == 0x01)) ) // correct bit + goodbits++; // count as a good bit + } + + // check too see if there were enough good bits to be successful + if (goodbits >= 8) + return TRUE; + } + else + OWERROR(OWERROR_BLOCK_FAILED); + + // block fail or device not present + return FALSE; +} + +//---------------------------------------------------------------------- +// Perform a overdrive MATCH command to select the 1-Wire device with +// the address in the ID data register. +// +// 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to +// OpenCOM to indicate the port number. +// +// Returns: TRUE: If the device is present on the 1-Wire Net and +// can do overdrive then the device is selected. +// FALSE: Device is not present or not capable of overdrive. +// +// *Note: This function could be converted to send DS2480 +// commands in one packet. +// +SMALLINT owOverdriveAccess(int portnum) +{ + uchar sendpacket[8]; + uchar i, bad_echo = FALSE; + + // make sure normal level + owLevel(portnum,MODE_NORMAL); + + // force to normal communication speed + owSpeed(portnum,MODE_NORMAL); + + // call the 1-Wire Net reset function + if (owTouchReset(portnum)) + { + // send the match command 0x69 + if (owWriteByte(portnum,0x69)) + { + // switch to overdrive communication speed + owSpeed(portnum,MODE_OVERDRIVE); + + // create a buffer to use with block function + // Serial Number + for (i = 0; i < 8; i++) + sendpacket[i] = SerialNum[portnum][i]; + + // send/recieve the transfer buffer + if (owBlock(portnum,FALSE,sendpacket,8)) + { + // verify that the echo of the writes was correct + for (i = 0; i < 8; i++) + if (sendpacket[i] != SerialNum[portnum][i]) + bad_echo = TRUE; + // if echo ok then success + if (!bad_echo) + return TRUE; + else + OWERROR(OWERROR_WRITE_VERIFY_FAILED); + } + else + OWERROR(OWERROR_BLOCK_FAILED); + } + else + OWERROR(OWERROR_WRITE_BYTE_FAILED); + } + else + OWERROR(OWERROR_NO_DEVICES_ON_NET); + + // failure, force back to normal communication speed + owSpeed(portnum,MODE_NORMAL); + + return FALSE; +} + +//-------------------------------------------------------------------------- +// Bit utility to read and write a bit in the buffer 'buf'. +// +// 'op' - operation (1) to set and (0) to read +// 'state' - set (1) or clear (0) if operation is write (1) +// 'loc' - bit number location to read or write +// 'buf' - pointer to array of bytes that contains the bit +// to read or write +// +// Returns: 1 if operation is set (1) +// 0/1 state of bit number 'loc' if operation is reading +// +static SMALLINT bitacc(SMALLINT op, SMALLINT state, SMALLINT loc, uchar *buf) +{ + SMALLINT nbyt,nbit; + + nbyt = (loc / 8); + nbit = loc - (nbyt * 8); + + if (op == WRITE_FUNCTION) + { + if (state) + buf[nbyt] |= (0x01 << nbit); + else + buf[nbyt] &= ~(0x01 << nbit); + + return 1; + } + else + return ((buf[nbyt] >> nbit) & 0x01); +} diff --git a/src/plugins/pro1_data_zip/ow/owsesu.c b/src/plugins/pro1_data_zip/ow/owsesu.c new file mode 100644 index 0000000..fa93023 --- /dev/null +++ b/src/plugins/pro1_data_zip/ow/owsesu.c @@ -0,0 +1,116 @@ +//--------------------------------------------------------------------------- +// Copyright (C) 2000 Dallas Semiconductor Corporation, All Rights Reserved. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL DALLAS SEMICONDUCTOR BE LIABLE FOR ANY CLAIM, DAMAGES +// OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// +// Except as contained in this notice, the name of Dallas Semiconductor +// shall not be used except as stated in the Dallas Semiconductor +// Branding Policy. +//--------------------------------------------------------------------------- +// +// owSesU.C - Acquire and release a Session on the 1-Wire Net. +// +// Version: 2.01 +// +// History: 1.03 -> 2.00 Changed 'MLan' to 'ow'. Added support for +// multiple ports. +// 2.00 -> 2.01 Added error handling. Added circular-include check. +// 2.01 -> 2.10 Added raw memory error handling and SMALLINT +// 2.10 -> 3.00 Added memory bank functionality +// Added file I/O operations +// + +#include "ownet.h" +#include "ds2480.h" + +//--------------------------------------------------------------------------- +// Attempt to acquire a 1-Wire net using a com port and a DS2480 based +// adapter. +// +// 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to +// OpenCOM to indicate the port number. +// 'port_zstr' - zero terminated port name. For this platform +// use format COMX where X is the port number. +// +// Returns: TRUE - success, COM port opened +// +// exportable functions defined in ownetu.c +SMALLINT owAcquire(int portnum, char *port_zstr) +{ + // attempt to open the communications port + if (OpenCOM(portnum,port_zstr) < 0) + { + OWERROR(OWERROR_OPENCOM_FAILED); + return FALSE; + } + + // detect DS2480 + if (!DS2480Detect(portnum)) + { + CloseCOM(portnum); + OWERROR(OWERROR_DS2480_NOT_DETECTED); + return FALSE; + } + + return TRUE; +} + +//--------------------------------------------------------------------------- +// Attempt to acquire a 1-Wire net using a com port and a DS2480 based +// adapter. +// +// 'port_zstr' - zero terminated port name. For this platform +// use format COMX where X is the port number. +// +// Returns: valid handle, or -1 if an error occurred +// +// exportable functions defined in ownetu.c +// +int owAcquireEx(const char *port_zstr) +{ + int portnum; + + // attempt to open the communications port + if ((portnum = OpenCOMEx(port_zstr)) < 0) + { + OWERROR(OWERROR_OPENCOM_FAILED); + return -1; + } + + // detect DS2480 + if (!DS2480Detect(portnum)) + { + CloseCOM(portnum); + OWERROR(OWERROR_DS2480_NOT_DETECTED); + return -1; + } + + return portnum; +} + +//--------------------------------------------------------------------------- +// Release the previously acquired a 1-Wire net. +// +// 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to +// OpenCOM to indicate the port number. +// +void owRelease(int portnum) +{ + CloseCOM(portnum); +} diff --git a/src/plugins/pro1_data_zip/ow/owtrnu.c b/src/plugins/pro1_data_zip/ow/owtrnu.c new file mode 100644 index 0000000..b6c46d6 --- /dev/null +++ b/src/plugins/pro1_data_zip/ow/owtrnu.c @@ -0,0 +1,597 @@ +//--------------------------------------------------------------------------- +// Copyright (C) 2000 Dallas Semiconductor Corporation, All Rights Reserved. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL DALLAS SEMICONDUCTOR BE LIABLE FOR ANY CLAIM, DAMAGES +// OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// +// Except as contained in this notice, the name of Dallas Semiconductor +// shall not be used except as stated in the Dallas Semiconductor +// Branding Policy. +//--------------------------------------------------------------------------- +// +// owTranU.C - Transport functions for 1-Wire Net +// using the DS2480B (U) serial interface chip. +// +// Version: 2.01 +// +// History: 1.02 -> 1.03 Removed caps in #includes for Linux capatibility +// 1.03 -> 2.00 Changed 'MLan' to 'ow'. Added support for +// multiple ports. +// 2.00 -> 2.01 Added support for owError library +// 2.01 -> 2.10 Added SMALLINT for small processors and error +// handling plus the raw memory utilities. +// 2.10 -> 3.00 Added memory bank functionality +// Added file I/O operations +// + +#include "ownet.h" +#include "ds2480.h" +// external defined in ds2480ut.c +extern SMALLINT UBaud[MAX_PORTNUM]; +extern SMALLINT UMode[MAX_PORTNUM]; +extern SMALLINT USpeed[MAX_PORTNUM]; +extern uchar SerialNum[MAX_PORTNUM][8]; + +// local static functions +static SMALLINT Write_Scratchpad(int,uchar *,int,SMALLINT); +static SMALLINT Copy_Scratchpad(int,int,SMALLINT); + +//-------------------------------------------------------------------------- +// The 'owBlock' transfers a block of data to and from the +// 1-Wire Net with an optional reset at the begining of communication. +// The result is returned in the same buffer. +// +// 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to +// indicate the symbolic port number. +// 'do_reset' - cause a owTouchReset to occure at the begining of +// communication TRUE(1) or not FALSE(0) +// 'tran_buf' - pointer to a block of unsigned +// chars of length 'tran_len' that will be sent +// to the 1-Wire Net +// 'tran_len' - length in bytes to transfer + +// Supported devices: all +// +// Returns: TRUE (1) : The optional reset returned a valid +// presence (do_reset == TRUE) or there +// was no reset required. +// FALSE (0): The reset did not return a valid prsence +// (do_reset == TRUE). +// +// The maximum tran_length is (160) +// +SMALLINT owBlock(int portnum, SMALLINT do_reset, uchar *tran_buf, SMALLINT tran_len) +{ + uchar sendpacket[320]; + uchar sendlen=0, i; + + // check for a block too big + if (tran_len > 160) + { + OWERROR(OWERROR_BLOCK_TOO_BIG); + return FALSE; + } + + // check if need to do a owTouchReset first + if (do_reset) + { + if (!owTouchReset(portnum)) + { + OWERROR(OWERROR_NO_DEVICES_ON_NET); + return FALSE; + } + } + + // construct the packet to send to the DS2480 + // check if correct mode + if (UMode[portnum] != MODSEL_DATA) + { + UMode[portnum] = MODSEL_DATA; + sendpacket[sendlen++] = MODE_DATA; + } + + // add the bytes to send + for (i = 0; i < tran_len; i++) + { + sendpacket[sendlen++] = tran_buf[i]; + + // check for duplication of data that looks like COMMAND mode + if (tran_buf[i] == MODE_COMMAND) + sendpacket[sendlen++] = tran_buf[i]; + } + + // flush the buffers + FlushCOM(portnum); + + // send the packet + if (WriteCOM(portnum,sendlen,sendpacket)) + { + // read back the response + if (ReadCOM(portnum,tran_len,tran_buf) == tran_len) + return TRUE; + else + OWERROR(OWERROR_READCOM_FAILED); + } + else + OWERROR(OWERROR_WRITECOM_FAILED); + + // an error occured so re-sync with DS2480 + DS2480Detect(portnum); + + return FALSE; +} + +//-------------------------------------------------------------------------- +// Read a Universal Data Packet from a standard NVRAM iButton +// and return it in the provided buffer. The page that the +// packet resides on is 'start_page'. Note that this function is limited +// to single page packets. The buffer 'read_buf' must be at least +// 29 bytes long. +// +// The Universal Data Packet always start on page boundaries but +// can end anywhere. The length is the number of data bytes not +// including the length byte and the CRC16 bytes. There is one +// length byte. The CRC16 is first initialized to the starting +// page number. This provides a check to verify the page that +// was intended is being read. The CRC16 is then calculated over +// the length and data bytes. The CRC16 is then inverted and stored +// low byte first followed by the high byte. +// +// Supported devices: DS1992, DS1993, DS1994, DS1995, DS1996, DS1982, +// DS1985, DS1986, DS2407, and DS1971. +// +// 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to +// indicate the symbolic port number. +// 'do_access' - flag to indicate if an 'owAccess' should be +// peformed at the begining of the read. This may +// be FALSE (0) if the previous call was to read the +// previous page (start_page-1). +// 'start_page' - page number to start the read from +// 'read_buf' - pointer to a location to store the data read +// +// Returns: >=0 success, number of data bytes in the buffer +// -1 failed to read a valid UDP +// +// +SMALLINT owReadPacketStd(int portnum, SMALLINT do_access, int start_page, uchar *read_buf) +{ + uchar i,length,sendlen=0,head_len=0; + uchar sendpacket[50]; + ushort lastcrc16; + + // check if access header is done + // (only use if in sequention read with one access at begining) + if (do_access) + { + // match command + sendpacket[sendlen++] = 0x55; + for (i = 0; i < 8; i++) + sendpacket[sendlen++] = SerialNum[portnum][i]; + // read memory command + sendpacket[sendlen++] = 0xF0; + // write the target address + sendpacket[sendlen++] = ((start_page << 5) & 0xFF); + sendpacket[sendlen++] = (start_page >> 3); + // check for DS1982 exception (redirection byte) + if (SerialNum[portnum][0] == 0x09) + sendpacket[sendlen++] = 0xFF; + // record the header length + head_len = sendlen; + } + // read the entire page length byte + for (i = 0; i < 32; i++) + sendpacket[sendlen++] = 0xFF; + + // send/recieve the transfer buffer + if (owBlock(portnum,do_access,sendpacket,sendlen)) + { + // seed crc with page number + setcrc16(portnum,(ushort)start_page); + + // attempt to read UDP from sendpacket + length = sendpacket[head_len]; + docrc16(portnum,(ushort)length); + + // verify length is not too large + if (length <= 29) + { + // loop to read packet including CRC + for (i = 0; i < length; i++) + { + read_buf[i] = sendpacket[i+1+head_len]; + docrc16(portnum,read_buf[i]); + } + + // read and compute the CRC16 + docrc16(portnum,sendpacket[i+1+head_len]); + lastcrc16 = docrc16(portnum,sendpacket[i+2+head_len]); + + // verify the CRC16 is correct + if (lastcrc16 == 0xB001) + return length; // return number of byte in record + else + OWERROR(OWERROR_CRC_FAILED); + } + else + OWERROR(OWERROR_INCORRECT_CRC_LENGTH); + } + else + OWERROR(OWERROR_BLOCK_FAILED); + + // failed block or incorrect CRC + return -1; +} + +//-------------------------------------------------------------------------- +// Write a Universal Data Packet onto a standard NVRAM 1-Wire device +// on page 'start_page'. This function is limited to UDPs that +// fit on one page. The data to write is provided as a buffer +// 'write_buf' with a length 'write_len'. +// +// The Universal Data Packet always start on page boundaries but +// can end anywhere. The length is the number of data bytes not +// including the length byte and the CRC16 bytes. There is one +// length byte. The CRC16 is first initialized to the starting +// page number. This provides a check to verify the page that +// was intended is being read. The CRC16 is then calculated over +// the length and data bytes. The CRC16 is then inverted and stored +// low byte first followed by the high byte. +// +// Supported devices: is_eprom=0 +// DS1992, DS1993, DS1994, DS1995, DS1996 +// is_eprom=1, crc_type=0(CRC8) +// DS1982 +// is_eprom=1, crc_type=1(CRC16) +// DS1985, DS1986, DS2407 +// +// 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to +// indicate the symbolic port number. +// 'start_page' - page number to write packet to +// 'write_buf' - pointer to buffer containing data to write +// 'write_len' - number of data byte in write_buf +// 'is_eprom' - flag set if device is an EPROM (1 EPROM, 0 NVRAM) +// 'crc_type' - if is_eprom=1 then indicates CRC type +// (0 CRC8, 1 CRC16) +// +// Returns: TRUE(1) success, packet written +// FALSE(0) failure to write, contact lost or device locked +// +SMALLINT owWritePacketStd(int portnum, int start_page, uchar *write_buf, + SMALLINT write_len, SMALLINT is_eprom, SMALLINT crc_type) +{ + uchar construct_buffer[32]; + uchar i,buffer_cnt=0,start_address,do_access; + ushort lastcrc16 = 0; + + // check to see if data too long to fit on device + if (write_len > 29) + return FALSE; + + // seed crc with page number + setcrc16(portnum,(ushort)start_page); + + // set length byte + construct_buffer[buffer_cnt++] = (uchar)(write_len); + docrc16(portnum,(ushort)write_len); + + // fill in the data to write + for (i = 0; i < write_len; i++) + { + lastcrc16 = docrc16(portnum,write_buf[i]); + construct_buffer[buffer_cnt++] = write_buf[i]; + } + + // add the crc + construct_buffer[buffer_cnt++] = (uchar)(~(lastcrc16 & 0xFF)); + construct_buffer[buffer_cnt++] = (uchar)(~((lastcrc16 & 0xFF00) >> 8)); + + // check if not EPROM + if (!is_eprom) + { + // write the page + if (!Write_Scratchpad(portnum,construct_buffer,start_page,buffer_cnt)) + { + OWERROR(OWERROR_WRITE_SCRATCHPAD_FAILED); + return FALSE; + } + + // copy the scratchpad + if (!Copy_Scratchpad(portnum,start_page,buffer_cnt)) + { + OWERROR(OWERROR_COPY_SCRATCHPAD_FAILED); + return FALSE; + } + + // copy scratch pad was good then success + return TRUE; + } + // is EPROM + else + { + // calculate the start address + start_address = ((start_page >> 3) << 8) | ((start_page << 5) & 0xFF); + do_access = TRUE; + // loop to program each byte + for (i = 0; i < buffer_cnt; i++) + { + if (owProgramByte(portnum,construct_buffer[i], start_address + i, + 0x0F, crc_type, do_access) != construct_buffer[i]) + { + OWERROR(OWERROR_PROGRAM_BYTE_FAILED); + return FALSE; + } + do_access = FALSE; + } + return TRUE; + } +} + +//-------------------------------------------------------------------------- +// Write a byte to an EPROM 1-Wire device. +// +// Supported devices: crc_type=0(CRC8) +// DS1982 +// crc_type=1(CRC16) +// DS1985, DS1986, DS2407 +// +// 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to +// indicate the symbolic port number. +// 'write_byte' - byte to program +// 'addr' - address of byte to program +// 'write_cmd' - command used to write (0x0F reg mem, 0x55 status) +// 'crc_type' - CRC used (0 CRC8, 1 CRC16) +// 'do_access' - Flag to access device for each byte +// (0 skip access, 1 do the access) +// WARNING, only use do_access=0 if programing the NEXT +// byte immediatly after the previous byte. +// +// Returns: >=0 success, this is the resulting byte from the program +// effort +// -1 error, device not connected or program pulse voltage +// not available +// +SMALLINT owProgramByte(int portnum, SMALLINT write_byte, int addr, SMALLINT write_cmd, + SMALLINT crc_type, SMALLINT do_access) +{ + ushort lastcrc16; + uchar lastcrc8; + + // optionally access the device + if (do_access) + { + if (!owAccess(portnum)) + { + OWERROR(OWERROR_ACCESS_FAILED); + return -1; + } + + // send the write command + if (!owWriteByte(portnum,write_cmd)) + { + OWERROR(OWERROR_WRITE_BYTE_FAILED); + return -1; + } + + // send the address + if (!owWriteByte(portnum,addr & 0xFF) || !owWriteByte(portnum,addr >> 8)) + { + OWERROR(OWERROR_WRITE_BYTE_FAILED); + return -1; + } + } + + // send the data to write + if (!owWriteByte(portnum,write_byte)) + { + OWERROR(OWERROR_WRITE_BYTE_FAILED); + return -1; + } + + // read the CRC + if (crc_type == 0) + { + // calculate CRC8 + if (do_access) + { + setcrc8(portnum,0); + docrc8(portnum,(uchar)write_cmd); + docrc8(portnum,(uchar)(addr & 0xFF)); + docrc8(portnum,(uchar)(addr >> 8)); + } + else + setcrc8(portnum,(uchar)(addr & 0xFF)); + + docrc8(portnum,(uchar)write_byte); + // read and calculate the read crc + lastcrc8 = docrc8(portnum,(uchar)owReadByte(portnum)); + // crc should now be 0x00 + if (lastcrc8 != 0) + { + OWERROR(OWERROR_CRC_FAILED); + return -1; + } + } + else + { + // CRC16 + if (do_access) + { + setcrc16(portnum,0); + docrc16(portnum,(ushort)write_cmd); + docrc16(portnum,(ushort)(addr & 0xFF)); + docrc16(portnum,(ushort)(addr >> 8)); + } + else + setcrc16(portnum,(ushort)addr); + docrc16(portnum,(ushort)write_byte); + // read and calculate the read crc + docrc16(portnum,(ushort)owReadByte(portnum)); + lastcrc16 = docrc16(portnum,(ushort)owReadByte(portnum)); + // crc should now be 0xB001 + if (lastcrc16 != 0xB001) + { + OWERROR(OWERROR_CRC_FAILED); + return -1; + } + } + + // send the program pulse + if (!owProgramPulse(portnum)) + { + OWERROR(OWERROR_PROGRAM_PULSE_FAILED); + return -1; + } + + // read back and return the resulting byte + return owReadByte(portnum); +} + +//-------------------------------------------------------------------------- +// Write the scratchpad of a standard NVRam device such as the DS1992,3,4 +// and verify its contents. +// +// 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to +// indicate the symbolic port number. +// 'write_buf' - pointer to buffer containing data to write +// 'start_page' - page number to write packet to +// 'write_len' - number of data byte in write_buf +// +// Returns: TRUE(1) success, the data was written and verified +// FALSE(0) failure, the data could not be written +// +// +SMALLINT Write_Scratchpad(int portnum, uchar *write_buf, int start_page, SMALLINT write_len) +{ + uchar i,sendlen=0; + uchar sendpacket[50]; + + // match command + sendpacket[sendlen++] = 0x55; + for (i = 0; i < 8; i++) + sendpacket[sendlen++] = SerialNum[portnum][i]; + // write scratchpad command + sendpacket[sendlen++] = 0x0F; + // write the target address + sendpacket[sendlen++] = ((start_page << 5) & 0xFF); + sendpacket[sendlen++] = (start_page >> 3); + + // write packet bytes + for (i = 0; i < write_len; i++) + sendpacket[sendlen++] = write_buf[i]; + + // send/recieve the transfer buffer + if (owBlock(portnum,TRUE,sendpacket,sendlen)) + { + // now attempt to read back to check + sendlen = 0; + // match command + sendpacket[sendlen++] = 0x55; + for (i = 0; i < 8; i++) + sendpacket[sendlen++] = SerialNum[portnum][i]; + // read scratchpad command + sendpacket[sendlen++] = 0xAA; + // read the target address, offset and data + for (i = 0; i < (write_len + 3); i++) + sendpacket[sendlen++] = 0xFF; + + // send/recieve the transfer buffer + if (owBlock(portnum,TRUE,sendpacket,sendlen)) + { + // check address and offset of scratchpad read + if ((sendpacket[10] != ((start_page << 5) & 0xFF)) || + (sendpacket[11] != (start_page >> 3)) || + (sendpacket[12] != (write_len - 1))) + { + OWERROR(OWERROR_READ_VERIFY_FAILED); + return FALSE; + } + + // verify each data byte + for (i = 0; i < write_len; i++) + if (sendpacket[i+13] != write_buf[i]) + { + OWERROR(OWERROR_WRITE_VERIFY_FAILED); + return FALSE; + } + + // must have verified + return TRUE; + } + else + OWERROR(OWERROR_BLOCK_FAILED); + } + else + OWERROR(OWERROR_BLOCK_FAILED); + + // failed a block tranfer + return FALSE; +} + +//-------------------------------------------------------------------------- +// Copy the contents of the scratchpad to its intended nv ram page. The +// page and length of the data is needed to build the authorization bytes +// to copy. +// +// 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to +// indicate the symbolic port number. +// 'start_page' - page number to write packet to +// 'write_len' - number of data bytes that are being copied +// +// Returns: TRUE(1) success +// FALSE(0) failure +// +SMALLINT Copy_Scratchpad(int portnum, int start_page, SMALLINT write_len) +{ + uchar i,sendlen=0; + uchar sendpacket[50]; + + // match command + sendpacket[sendlen++] = 0x55; + for (i = 0; i < 8; i++) + sendpacket[sendlen++] = SerialNum[portnum][i]; + // copy scratchpad command + sendpacket[sendlen++] = 0x55; + // write the target address + sendpacket[sendlen++] = ((start_page << 5) & 0xFF); + sendpacket[sendlen++] = (start_page >> 3); + sendpacket[sendlen++] = write_len - 1; + // read copy result + sendpacket[sendlen++] = 0xFF; + + // send/recieve the transfer buffer + if (owBlock(portnum,TRUE,sendpacket,sendlen)) + { + // check address and offset of scratchpad read + if ((sendpacket[10] != ((start_page << 5) & 0xFF)) || + (sendpacket[11] != (start_page >> 3)) || + (sendpacket[12] != (write_len - 1)) || + (sendpacket[13] & 0xF0)) + { + OWERROR(OWERROR_READ_VERIFY_FAILED); + return FALSE; + } + else + return TRUE; + } + else + OWERROR(OWERROR_BLOCK_FAILED); + + // failed a block tranfer + return FALSE; +} + diff --git a/src/plugins/pro1_data_zip/ow/sha18.c b/src/plugins/pro1_data_zip/ow/sha18.c new file mode 100644 index 0000000..de49dce --- /dev/null +++ b/src/plugins/pro1_data_zip/ow/sha18.c @@ -0,0 +1,911 @@ +//--------------------------------------------------------------------------- +// Copyright (C) 2000 Dallas Semiconductor Corporation, All Rights Reserved. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL DALLAS SEMICONDUCTOR BE LIABLE FOR ANY CLAIM, DAMAGES +// OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// +// Except as contained in this notice, the name of Dallas Semiconductor +// shall not be used except as stated in the Dallas Semiconductor +// Branding Policy. +//--------------------------------------------------------------------------- +// +// sha18.c - Low-level memory and SHA functions for the DS1963S. +// +// Version: 2.10 +// + +#include "ownet.h" +#include "shaib.h" + +//-------------------------------------------------------------------------- +// Attempt to erase the scratchpad of the specified SHA iButton for DS1963S. +// +// 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to +// indicate the symbolic port number. +// 'address' - value for TA2/TA1 (Note: TA2/TA1 aren't always set by +// Erase Scratchpad command.) +// 'resume' - if true, device access is resumed using the RESUME +// ROM command (0xA5). Otherwise, a a MATCH ROM is +// used along with the device's entire address number. +// +// Returns: TRUE, success, scratchpad erased +// FALSE, failure to erase scratchpad +// +SMALLINT EraseScratchpadSHA18(int portnum, int address, SMALLINT resume) +{ + uchar send_block[50]; + int num_verf; + short send_cnt=0; + + if(!resume) + { + // access the device + OWASSERT( SelectSHA(portnum), OWERROR_ACCESS_FAILED, FALSE ); + } + else + { + // transmit RESUME command + send_block[send_cnt++] = ROM_CMD_RESUME; + } + + // change number of verification bytes if in overdrive + num_verf = (in_overdrive[portnum&0x0FF]) ? 6 : 2; + + // erase scratchpad command + send_block[send_cnt++] = CMD_ERASE_SCRATCHPAD; + // TA1 + send_block[send_cnt++] = (uchar)(address & 0xFF); + // TA2 + send_block[send_cnt++] = (uchar)((address >> 8) & 0xFF); + + // now add the verification bytes + //for (i = 0; i < num_verf; i++) + // send_block[send_cnt++] = 0xFF; + memset(&send_block[send_cnt], 0x0FF, num_verf); + send_cnt += num_verf; + + // now send the block + OWASSERT( owBlock(portnum,resume,send_block,send_cnt), + OWERROR_BLOCK_FAILED, FALSE ); + + //\\//\\//\\//\\//\\//\\//\\//\\//\\// + #ifdef DEBUG_DUMP + debugout(send_block,send_cnt); + #endif + //\\//\\//\\//\\//\\//\\//\\//\\//\\// + + // check verification + OWASSERT( ((send_block[send_cnt-1] & 0xF0) == 0x50) || + ((send_block[send_cnt-1] & 0xF0) == 0xA0), + OWERROR_NO_COMPLETION_BYTE, FALSE); + + return TRUE; +} + +//---------------------------------------------------------------------- +// Read the scratchpad with CRC16 verification for DS1963S. +// +// 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to +// indicate the symbolic port number. +// 'address' - pointer to address that is read from scratchpad +// 'es' - pointer to offset byte read from scratchpad +// 'data' - pointer data buffer read from scratchpad +// 'resume' - if true, device access is resumed using the RESUME +// ROM command (0xA5). Otherwise, a a MATCH ROM is +// used along with the device's entire address number. +// +// Return: TRUE - scratch read, address, es, and data returned +// FALSE - error reading scratch, device not present +// +// +SMALLINT ReadScratchpadSHA18(int portnum, int* address, uchar* es, + uchar* data, SMALLINT resume) +{ + short send_cnt=0; + uchar send_block[40]; + SMALLINT i; + ushort lastcrc16; + int bytes_read; + + if(!resume) + { + // access the device + OWASSERT( SelectSHA(portnum), OWERROR_ACCESS_FAILED, FALSE ); + } + else + { + // transmit RESUME command + send_block[send_cnt++] = ROM_CMD_RESUME; + resume = 1; // for addition later + } + + // read scratchpad command + send_block[send_cnt++] = CMD_READ_SCRATCHPAD; + + // now add the read bytes for data bytes and crc16 + memset(&send_block[send_cnt], 0xff, 37); + send_cnt += 37; + + // now send the block + OWASSERT( owBlock(portnum,resume,send_block,send_cnt), + OWERROR_BLOCK_FAILED, FALSE ); + + //\\//\\//\\//\\//\\//\\//\\//\\//\\// + #ifdef DEBUG_DUMP + debugout(send_block,send_cnt); + #endif + //\\//\\//\\//\\//\\//\\//\\//\\//\\// + + bytes_read = (send_block[2+resume] << 8) | send_block[1+resume]; + bytes_read = 32 - (bytes_read & 0x1F); + + // calculate CRC16 of result + setcrc16(portnum,0); + for (i = resume; i < bytes_read + resume + 6; i++) + lastcrc16 = docrc16(portnum,send_block[i]); + + // verify CRC16 is correct + OWASSERT( lastcrc16==0xB001, OWERROR_CRC_FAILED, FALSE ); + + // copy data to return buffers + if(address) + *address = (send_block[2+resume] << 8) | send_block[1+resume]; + if(es) + *es = send_block[3+resume]; + + memcpy(data, &send_block[4+resume], 32); + + // success + return TRUE; +} + +//---------------------------------------------------------------------- +// Write the scratchpad with CRC16 verification for DS1963S. The data +// is padded until the offset is 0x1F so that the CRC16 is retrieved. +// +// 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to +// indicate the symbolic port number. +// 'address' - address to write data to +// 'data' - data to write +// 'data_len' - number of bytes of data to write +// 'resume' - if true, device access is resumed using the RESUME +// ROM command (0xA5). Otherwise, a a MATCH ROM is +// used along with the device's entire address number. +// +// Return: TRUE - write to scratch verified +// FALSE - error writing scratch, device not present, or HIDE +// flag is in incorrect state for address being written. +// +SMALLINT WriteScratchpadSHA18(int portnum, int address, const uchar *data, + SMALLINT data_len, SMALLINT resume) +{ + uchar send_block[50]; + short send_cnt=0,i; + ushort lastcrc16; + + if(!resume) + { + // access the device + OWASSERT( SelectSHA(portnum), OWERROR_ACCESS_FAILED, FALSE ); + } + else + { + // transmit RESUME command + send_block[send_cnt++] = ROM_CMD_RESUME; + } + + setcrc16(portnum,0); + // write scratchpad command + send_block[send_cnt] = CMD_WRITE_SCRATCHPAD; + lastcrc16 = docrc16(portnum,send_block[send_cnt++]); + // address 1 + send_block[send_cnt] = (uchar)(address & 0xFF); + lastcrc16 = docrc16(portnum,send_block[send_cnt++]); + // address 2 + send_block[send_cnt] = (uchar)((address >> 8) & 0xFF); + lastcrc16 = docrc16(portnum,send_block[send_cnt++]); + // data + for (i = 0; i < data_len; i++) + { + send_block[send_cnt] = data[i]; + lastcrc16 = docrc16(portnum,send_block[send_cnt++]); + } + // pad if needed + for (i = 0; i < (0x1F - ((address + data_len - 1) & 0x1F)); i++) + { + send_block[send_cnt] = 0xFF; + lastcrc16 = docrc16(portnum,send_block[send_cnt++]); + } + // CRC16 + send_block[send_cnt++] = 0xFF; + send_block[send_cnt++] = 0xFF; + + // now send the block + OWASSERT( owBlock(portnum,resume,send_block,send_cnt), + OWERROR_BLOCK_FAILED, FALSE ); + + //\\//\\//\\//\\//\\//\\//\\//\\//\\// + #ifdef DEBUG_DUMP + debugout(send_block,send_cnt); + #endif + //\\//\\//\\//\\//\\//\\//\\//\\//\\// + + // perform CRC16 of last 2 byte in packet + for (i = send_cnt - 2; i < send_cnt; i++) + lastcrc16 = docrc16(portnum,send_block[i]); + + // verify CRC16 is correct + OWASSERT( lastcrc16==0xB001, OWERROR_CRC_FAILED, FALSE ); + + // success + return TRUE; +} + + +//---------------------------------------------------------------------- +// Copy the scratchpad with verification for DS1963S. Assume that the +// data was padded to get the CRC16 verification on write scratchpad. +// This will result in the 'es' byte to be 0x1F. +// +// 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to +// indicate the symbolic port number. +// 'address' - address of destination +// 'len' - length of data +// 'resume' - if true, device access is resumed using the RESUME +// ROM command (0xA5). Otherwise, a a MATCH ROM is +// used along with the device's entire address number. +// +// Return: TRUE - copy scratch verified +// FALSE - error during copy scratch, device not present, or HIDE +// flag is in incorrect state for address being written. +// +SMALLINT CopyScratchpadSHA18(int portnum, int address, + SMALLINT len, SMALLINT resume) +{ + short send_cnt=0; + uchar send_block[10]; + int num_verf; + uchar es = (address + len - 1) & 0x1F; + + if(!resume) + { + // access the device + OWASSERT( SelectSHA(portnum), OWERROR_ACCESS_FAILED, FALSE ); + } + else + { + // transmit RESUME command + send_block[send_cnt++] = ROM_CMD_RESUME; + } + + // change number of verification bytes if in overdrive + num_verf = (in_overdrive[portnum&0x0FF]) ? 4 : 2; + + // copy scratchpad command + send_block[send_cnt++] = CMD_COPY_SCRATCHPAD; + // address 1 + send_block[send_cnt++] = (uchar)(address & 0xFF); + // address 2 + send_block[send_cnt++] = (uchar)((address >> 8) & 0xFF); + // es + send_block[send_cnt++] = es; + + // verification bytes + memset(&send_block[send_cnt], 0x0FF, num_verf); + send_cnt += num_verf; + + // now send the block + OWASSERT( owBlock(portnum,resume,send_block,send_cnt), + OWERROR_BLOCK_FAILED, FALSE ); + + //\\//\\//\\//\\//\\//\\//\\//\\//\\// + #ifdef DEBUG_DUMP + debugout(send_block,send_cnt); + #endif + //\\//\\//\\//\\//\\//\\//\\//\\//\\// + + // check verification + OWASSERT( ((send_block[send_cnt-1] & 0xF0) == 0x50) || + ((send_block[send_cnt-1] & 0xF0) == 0xA0), + OWERROR_NO_COMPLETION_BYTE, FALSE ); + + return TRUE; +} + +//---------------------------------------------------------------------- +// Perform a scratchpad match using provided data. Fixed data length +// of 20 bytes. +// +// 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to +// indicate the symbolic port number. +// 'data' - data to use in match scratch operation +// 'resume' - if true, device access is resumed using the RESUME +// ROM command (0xA5). Otherwise, a a MATCH ROM is +// used along with the device's entire address number. +// +// Return: TRUE - valid match +// FALSE - no match or device not present +// +SMALLINT MatchScratchpadSHA18(int portnum, uchar* data, SMALLINT resume) +{ + short send_cnt=0; + uchar send_block[50]; + int i; + ushort lastcrc16; + + if(!resume) + { + // access the device + OWASSERT( SelectSHA(portnum), OWERROR_ACCESS_FAILED, FALSE ); + } + else + { + // transmit RESUME command + send_block[send_cnt++] = ROM_CMD_RESUME; + } + + setcrc16(portnum,0); + // match scratchpad command + send_block[send_cnt] = CMD_MATCH_SCRATCHPAD; + lastcrc16 = docrc16(portnum,send_block[send_cnt++]); + + // send 20 data bytes + for (i = 0; i < 20; i++) + { + send_block[send_cnt] = data[i]; + lastcrc16 = docrc16(portnum,send_block[send_cnt++]); + } + // send two crc bytes and verification byte + //for (i = 0; i < 3; i++) + // send_block[send_cnt++] = 0xFF; + memset(&send_block[send_cnt], 0x0FF, 3); + send_cnt += 3; + + // now send the block + OWASSERT( owBlock(portnum,resume,send_block,send_cnt), + OWERROR_BLOCK_FAILED, FALSE ); + + //\\//\\//\\//\\//\\//\\//\\//\\//\\// + #ifdef DEBUG_DUMP + debugout(send_block,send_cnt); + #endif + //\\//\\//\\//\\//\\//\\//\\//\\//\\// + + // check the CRC + for (i = (send_cnt - 3); i < (send_cnt - 1); i++) + lastcrc16 = docrc16(portnum,send_block[i]); + + // verify CRC16 is correct + OWASSERT( lastcrc16==0xB001, OWERROR_CRC_FAILED, FALSE ); + + // check verification + if(send_block[send_cnt - 1] != (uchar)0xFF) + return TRUE; + else + return FALSE; +} + +//---------------------------------------------------------------------- +// Read Memory Page for DS1963S. +// +// 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to +// indicate the symbolic port number. +// 'pagenum' - page number to do a read authenticate +// 'data' - buffer to read into from page +// 'resume' - if true, device access is resumed using the RESUME +// ROM command (0xA5). Otherwise, a a MATCH ROM is +// used along with the device's entire address number. +// +// Return: TRUE - Read successfull +// FALSE - error occurred during read. +// +SMALLINT ReadMemoryPageSHA18(int portnum, SMALLINT pagenum, + uchar* data, SMALLINT resume) +{ + short send_cnt=0; + uchar send_block[36]; + int address = pagenum << 5; + + if(!resume) + { + // access the device + OWASSERT( SelectSHA(portnum), OWERROR_ACCESS_FAILED, -1 ); + } + else + { + // transmit RESUME command + send_block[send_cnt++] = ROM_CMD_RESUME; + } + + // create the send block + // Read Memory command + send_block[send_cnt++] = CMD_READ_MEMORY; + // TA1 + send_block[send_cnt++] = (uchar)(address & 0xFF); + // TA2 + send_block[send_cnt++] = (uchar)((address >> 8) & 0xFF); + + // now add the read bytes for data bytes + memset(&send_block[send_cnt], 0x0FF, 32); + send_cnt += 32; + + // now send the block + OWASSERT( owBlock(portnum,TRUE,send_block,send_cnt), + OWERROR_BLOCK_FAILED, FALSE ); + + // transfer the results + memcpy(data, &send_block[send_cnt-32], 32); + + return TRUE; +} + +//---------------------------------------------------------------------- +// Read Authenticated Page for DS1963S. +// +// 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to +// indicate the symbolic port number. +// 'pagenum' - page number to do a read authenticate +// 'data' - buffer to read into from page +// 'sign' - buffer for storing sha computation +// 'resume' - if true, device access is resumed using the RESUME +// ROM command (0xA5). Otherwise, a a MATCH ROM is +// used along with the device's entire address number. +// +// Return: Value of write cycle counter for the page +// -1 for error +// +int ReadAuthPageSHA18(int portnum, SMALLINT pagenum, uchar* data, + uchar* sign, SMALLINT resume) +{ + short send_cnt=0; + uchar send_block[56]; + short num_verf; + SMALLINT i; + ushort lastcrc16; + int address = pagenum*32, wcc = -1; + + if(!resume) + { + // access the device + OWASSERT( SelectSHA(portnum), OWERROR_ACCESS_FAILED, -1 ); + } + else + { + // transmit RESUME command + send_block[send_cnt++] = ROM_CMD_RESUME; + } + + //seed the crc + setcrc16(portnum,0); + + // change number of verification bytes if in overdrive + num_verf = (in_overdrive[portnum&0x0FF]) ? 10 : 2; + + // create the send block + // Read Authenticated Page command + send_block[send_cnt] = CMD_READ_AUTH_PAGE; + lastcrc16 = docrc16(portnum, send_block[send_cnt++]); + + // TA1 + send_block[send_cnt] = (uchar)(address & 0xFF); + lastcrc16 = docrc16(portnum,send_block[send_cnt++]); + + // TA2 + send_block[send_cnt] = (uchar)((address >> 8) & 0xFF); + lastcrc16 = docrc16(portnum,send_block[send_cnt++]); + + // now add the read bytes for data bytes, counter, and crc16, verification + //for (i = 0; i < (42 + num_verf); i++) + // send_block[send_cnt++] = 0xFF; + memset(&send_block[send_cnt], 0x0FF, 42+num_verf); + send_cnt += 42+num_verf; + + // now send the block + OWASSERT( owBlock(portnum,resume,send_block,send_cnt), + OWERROR_BLOCK_FAILED, -1 ); + + //\\//\\//\\//\\//\\//\\//\\//\\//\\// + #ifdef DEBUG_DUMP + debugout(send_block,send_cnt); + #endif + //\\//\\//\\//\\//\\//\\//\\//\\//\\// + + // check the CRC + for (i = resume?4:3; i < (send_cnt - num_verf); i++) + lastcrc16 = docrc16(portnum,send_block[i]); + + // verify CRC16 is correct + OWASSERT( lastcrc16==0xB001, OWERROR_CRC_FAILED, -1); + + // check verification + OWASSERT( ((send_block[send_cnt-1] & 0xF0) == 0x50) || + ((send_block[send_cnt-1] & 0xF0) == 0xA0), + OWERROR_NO_COMPLETION_BYTE, -1); + + // transfer results + //cnt = 0; + //for (i = send_cnt - 42 - num_verf; i < (send_cnt - 10 - num_verf); i++) + // data[cnt++] = send_block[i]; + memcpy(data, &send_block[send_cnt-42-num_verf], 32); + + wcc = BytesToInt(&send_block[send_cnt-10-num_verf], 4); + + if(sign!=NULL) + { + OWASSERT( ReadScratchpadSHA18(portnum, 0, 0, send_block, TRUE), + OWERROR_READ_SCRATCHPAD_FAILED, FALSE ); + + //for(i=0; i<20; i++) + // sign[i] = send_block[i+8]; + memcpy(sign, &send_block[8], 20); + } + + return wcc; +} + +//---------------------------------------------------------------------- +// Write Data Page for DS1963S. +// +// 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to +// indicate the symbolic port number. +// 'pagenum' - page number to write to +// 'data' - buffer to write into page +// 'resume' - if true, device access is resumed using the RESUME +// ROM command (0xA5). Otherwise, a a MATCH ROM is +// used along with the device's entire address number. +// +// Return: TRUE - Write successfull +// FALSE - error occurred during write. +// +SMALLINT WriteDataPageSHA18(int portnum, SMALLINT pagenum, + uchar* data, SMALLINT resume) +{ + uchar buffer[32]; + int addr = pagenum << 5, addr_buff; + uchar es = 0; + + OWASSERT( EraseScratchpadSHA18(portnum, addr, resume), + OWERROR_ERASE_SCRATCHPAD_FAILED, FALSE ); + + OWASSERT( WriteScratchpadSHA18(portnum, addr, data, 32, TRUE), + OWERROR_WRITE_SCRATCHPAD_FAILED, FALSE ); + + OWASSERT( ReadScratchpadSHA18(portnum, &addr_buff, &es, buffer, TRUE), + OWERROR_READ_SCRATCHPAD_FAILED, FALSE ); + + // verify that what we read is exactly what we wrote + OWASSERT( (addr == addr_buff) && (es == 0x1F) + && (memcmp(buffer, data, 32)==0), + OWERROR_READ_SCRATCHPAD_FAILED, FALSE ); + + OWASSERT( CopyScratchpadSHA18(portnum, addr, 32, TRUE), + OWERROR_COPY_SCRATCHPAD_FAILED, FALSE ); + + return TRUE; + +} + +//---------------------------------------------------------------------- +// Compute sha command based on control_byte and page address. +// +// 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to +// indicate the symbolic port number. +// 'control_byte' - control byte used in sha operation +// 'address' - address used in compute sha operation +// 'resume' - if true, device access is resumed using the RESUME +// ROM command (0xA5). Otherwise, a a MATCH ROM is +// used along with the device's entire address number. +// +// Return: TRUE - compute sha finished +// FALSE - CRC error, device not present +// +SMALLINT SHAFunction18(int portnum, uchar control_byte, + int address, SMALLINT resume) +{ + short send_cnt=0; + uchar send_block[18]; + int i,num_verf; + ushort lastcrc16; + + if(!resume) + { + // access the device + OWASSERT( SelectSHA(portnum), OWERROR_ACCESS_FAILED, FALSE ); + } + else + { + // transmit RESUME command + send_block[send_cnt++] = ROM_CMD_RESUME; + } + + setcrc16(portnum,0); + // change number of verification bytes if in overdrive + num_verf = (in_overdrive[portnum&0x0FF]) ? 10 : 2; + + // Compute SHA Command + send_block[send_cnt] = CMD_COMPUTE_SHA; + lastcrc16 = docrc16(portnum,send_block[send_cnt++]); + // address 1 + send_block[send_cnt] = (uchar)(address & 0xFF); + lastcrc16 = docrc16(portnum,send_block[send_cnt++]); + // address 2 + send_block[send_cnt] = (uchar)((address >> 8) & 0xFF); + lastcrc16 = docrc16(portnum,send_block[send_cnt++]); + // control byte + send_block[send_cnt] = control_byte; + lastcrc16 = docrc16(portnum,send_block[send_cnt++]); + + // now read bytes crc16, and verification + //for (i = 0; i < 2 + num_verf; i++) + // send_block[send_cnt++] = 0xFF; + memset(&send_block[send_cnt], 0x0FF, 2+num_verf); + send_cnt += 2+num_verf; + + // now send the block + OWASSERT( owBlock(portnum,resume,send_block,send_cnt), + OWERROR_BLOCK_FAILED, FALSE ); + + //\\//\\//\\//\\//\\//\\//\\//\\//\\// + #ifdef DEBUG_DUMP + debugout(send_block,send_cnt); + #endif + //\\//\\//\\//\\//\\//\\//\\//\\//\\// + + // check the CRC + for (i = resume?5:4; i < (send_cnt - num_verf); i++) + lastcrc16 = docrc16(portnum,send_block[i]); + + // verify CRC16 is correct + OWASSERT( lastcrc16==0xB001, OWERROR_CRC_FAILED, FALSE ); + + // check verification + OWASSERT( ((send_block[send_cnt-1] & 0xF0) == 0x50) || + ((send_block[send_cnt-1] & 0xF0) == 0xA0), + OWERROR_NO_COMPLETION_BYTE, FALSE ); + + return TRUE; +} + +//---------------------------------------------------------------------- +// Copies hidden scratchpad data into specified secret. Resume command +// is used by default. +// +// 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to +// indicate the symbolic port number. +// 'secretnum' - secret number to replace with scratchpad data. +// +// Return: TRUE - copy secret succeeded +// FALSE - error or device not present +// +SMALLINT CopySecretSHA18(int portnum, SMALLINT secretnum) +{ + // change number of verification bytes if in overdrive + SMALLINT num_verf = (in_overdrive[portnum&0x0FF]) ? 10 : 2; + + // each page has 4 secrets, so look at 2 LS bits to + // determine offset in the page. + SMALLINT secret_offset = (secretnum&3) << 3; + + // secrets 0-3 are stored starting at address 0200h + // and 4-7 are stored starting at address 0220h. + int address = (secretnum<4 ? 0x0200 : 0x0220) + + secret_offset; + + SMALLINT length = 32 - secret_offset; + SMALLINT send_cnt = 0, i; + uchar send_block[38]; + ushort lastcrc16; + + //Since other functions must be called before this one + //that are communicating with the button, resume is assumed. + send_block[send_cnt++] = ROM_CMD_RESUME; + send_block[send_cnt++] = CMD_WRITE_SCRATCHPAD; + send_block[send_cnt++] = (uchar)address; + send_block[send_cnt++] = (uchar)(address>>8); + + //for(i=0; i32) + { + memcpy(&scratchpad[8], &secret[offset+32], + (bytes_left<47?bytes_left-32:15)); + } + + // write secret data into data page + OWASSERT( WriteDataPageSHA18(portnum, pagenum, data, resume), + OWERROR_WRITE_DATA_PAGE_FAILED, FALSE ); + + // write secret data into scratchpad + OWASSERT( WriteScratchpadSHA18(portnum, addr, scratchpad, 32, TRUE), + OWERROR_WRITE_SCRATCHPAD_FAILED, FALSE ); + + // perform secret computation + OWASSERT( SHAFunction18(portnum, + (uchar)(offset==0 ? SHA_COMPUTE_FIRST_SECRET + : SHA_COMPUTE_NEXT_SECRET), addr, TRUE), + OWERROR_SHA_FUNCTION_FAILED, FALSE ); + + // copy the resulting secret into secret location + OWASSERT( CopySecretSHA18(portnum, secretnum), + OWERROR_COPY_SECRET_FAILED, FALSE); + + resume = TRUE; + } + + return TRUE; +} + +//---------------------------------------------------------------------- +// Binds unique secret to DS1963S. bindData must be 32 bytes and +// bindCode must be 15 bytes. +// +// 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to +// indicate the symbolic port number. +// 'pagenum' - page number to do a read authenticate +// 'secretnum' - destination secret for computation results +// 'bindData' - the input data written to the data page for unique +// secret computation. +// 'bindCode' - the input data written to the scratchpad for unique +// secret computation. +// 'resume' - if true, device access is resumed using the RESUME +// ROM command (0xA5). Otherwise, a a MATCH ROM is +// used along with the device's entire address number. +// +// Return: TRUE - bind successfull +// FALSE - error occurred during secret installation. +// +SMALLINT BindSecretToiButton18(int portnum, SMALLINT pagenum, + SMALLINT secretnum, + uchar* bindData, uchar* bindCode, + SMALLINT resume) +{ + int addr = pagenum << 5; + uchar scratchpad[32]; + + memset(scratchpad, 0x00, 32); + memcpy(&scratchpad[8], bindCode, 15); + + // write secret data into data page + OWASSERT( WriteDataPageSHA18(portnum, pagenum, bindData, resume), + OWERROR_WRITE_DATA_PAGE_FAILED, FALSE ); + + // write secret data into scratchpad + OWASSERT( WriteScratchpadSHA18(portnum, addr, scratchpad, 32, TRUE), + OWERROR_WRITE_SCRATCHPAD_FAILED, FALSE ); + + // perform secret computation + OWASSERT( SHAFunction18(portnum, (uchar)SHA_COMPUTE_NEXT_SECRET, + addr, TRUE), + OWERROR_SHA_FUNCTION_FAILED, FALSE ); + + // copy the resulting secret into secret location + OWASSERT( CopySecretSHA18(portnum, secretnum), + OWERROR_COPY_SECRET_FAILED, FALSE); + + return TRUE; +} + + diff --git a/src/plugins/pro1_data_zip/ow/shaib.c b/src/plugins/pro1_data_zip/ow/shaib.c new file mode 100644 index 0000000..c2ac08e --- /dev/null +++ b/src/plugins/pro1_data_zip/ow/shaib.c @@ -0,0 +1,674 @@ +/*--------------------------------------------------------------------------- + * Copyright (C) 2000 Dallas Semiconductor Corporation, All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL DALLAS SEMICONDUCTOR BE LIABLE FOR ANY CLAIM, DAMAGES + * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of Dallas Semiconductor + * shall not be used except as stated in the Dallas Semiconductor + * Branding Policy. + *--------------------------------------------------------------------------- + * + * shaibutton.c - Protocol-level functions as well as useful utility + * functions for sha applications. + * + * Version: 2.10 + */ + +#include "ownet.h" +#include "shaib.h" + +/* Global */ +SMALLINT in_overdrive[MAX_PORTNUM]; + +/*--------------------------------------------------------------------- + * Uses File I/O API to find the coprocessor with a specific + * coprocessor file name. Usually 'COPR.0'. + * + * 'copr' - Structure for holding coprocessor information + * 'fe' - pointer to file entry structure, with proper filename. + * + * Returns: TRUE, found a valid coprocessor + * FALSE, no coprocessor is present + */ +#if 0 +SMALLINT FindCoprSHA(SHACopr* copr, FileEntry* fe) +{ + SMALLINT FoundCopr = FALSE; + int data; + + /* now get all the SHA iButton parts until we find + * one that has the right file on it. + */ + if(FindNewSHA(copr->portnum, copr->devAN, TRUE)) + { + do + { + short handle; + + if(owOpenFile(copr->portnum, copr->devAN, fe, &handle)) + { + int length = fe->NumPgs << 5; + uchar* raw = malloc(length*5); + + if(owReadFile(copr->portnum, copr->devAN, + handle, raw, + length, &length)) + { + if(!owCloseFile(copr->portnum, copr->devAN, handle)) + return FALSE; + if(raw != 0) + data = GetCoprFromRawData(copr, raw, length); + FoundCopr = TRUE; + } + + free(raw); + } + } + while(!FoundCopr && FindNewSHA(copr->portnum, copr->devAN, FALSE)); + } + + return FoundCopr; +} +#endif + +/*--------------------------------------------------------------------- + * Extracts coprocessor configuration information from raw data. + * Returns the last unaccessed index. + * + * 'copr' - Structure for holding coprocessor information + * 'raw' - Raw bytes, usually from file stored on disk or on the + * coprocessor itself. + * 'length' - The length of coprocessor data. + */ +int GetCoprFromRawData(SHACopr* copr, uchar* raw, int length) +{ + int i, namelen, siglen, auxlen; + /* copy in the name of the user's service file */ + memcpy(copr->serviceFilename, raw, 5); + + /* various page numbers */ + copr->signPageNumber = raw[5]; + copr->authPageNumber = raw[6]; + copr->wspcPageNumber = raw[7]; + + /* version information */ + copr->versionNumber = raw[8]; + + /* skip 4 bytes for date info; + * get bind data, bind code, and signing challenge + */ + memcpy(copr->bindData, &raw[13], 32); + memcpy(copr->bindCode, &raw[45], 7); + memcpy(copr->signChlg, &raw[52], 3); + + namelen = raw[55]; + siglen = raw[56]; + auxlen = raw[57]; + + /* read in provider name as null-terminated string */ + copr->providerName = malloc(namelen+1); + memcpy(copr->providerName, &raw[58], namelen); + copr->providerName[namelen] = '\0'; + + /* get initial signature */ + memcpy(copr->initSignature, &raw[58+namelen], + (siglen>20?20:siglen) ); + + /* read in auxilliary data as null-terminated string */ + copr->auxilliaryData = malloc(auxlen+1); + memcpy(copr->auxilliaryData, + &raw[58+namelen+siglen], auxlen); + copr->auxilliaryData[auxlen] = '\0'; + + /* encryption code */ + i = 58+namelen+siglen+auxlen; + copr->encCode = raw[i]; + + /* ds1961S compatibility flag - optional */ + if((length>i+1) && (raw[i+1]!=0)) + copr->ds1961Scompatible = TRUE; + else + copr->ds1961Scompatible = FALSE; + + return i+2; +} + +/*--------------------------------------------------------------------- + * Uses File I/O API to find the user token with a specific + * service file name. Usually 'DSLM.102'. + * + * 'user' - Structure for holding user token information + * 'fe' - pointer to file entry structure, with proper + * service filename. + * 'doBlocking' - if TRUE, method blocks until a user token is found. + * + * Returns: TRUE, found a valid user token + * FALSE, no user token is present + */ +#if 0 +SMALLINT FindUserSHA(SHAUser* user, FileEntry* fe, + SMALLINT doBlocking) +{ + SMALLINT FoundUser = FALSE; + + for(;;) + { + /* now get all the SHA iButton parts until we find + * one that has the right file on it. + */ + while(!FoundUser && FindNewSHA(user->portnum, user->devAN, FALSE)) + { + short handle; + + if(owOpenFile(user->portnum, user->devAN, fe, &handle)) + { + user->accountPageNumber = fe->Spage; + FoundUser = TRUE; + if(!owCloseFile(user->portnum, user->devAN, handle)) + return FALSE; + } + } + + if(FoundUser) + return TRUE; + else if(!doBlocking) + return FALSE; + } +} +#endif + +/* final buffer for tracking list of known SHA parts + * only holds the CRC for each part + */ +static uchar ListOfKnownSHA[MAX_PORTNUM][MAX_SHA_IBUTTONS]; +static int listIndex = 0; +/* intermediate buffer for tracking list of known SHA parts */ +static uchar listBuffer[MAX_PORTNUM][MAX_SHA_IBUTTONS]; +static int indexBuffer = 0; +/* holds last state of FindNewSHA */ +static SMALLINT needsFirst = FALSE; + +/*--------------------------------------------------------------------- + * Finds new SHA iButtons on the given port. Uses 'triple-buffer' + * technique to insure it only finds 'new' buttons. + * + * 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to + * indicate the symbolic port number. + * 'devAN' - pointer to buffer for device address + * 'resetList' - if TRUE, final buffer is cleared. + * + * Returns: TRUE, found a new SHA iButton. + * FALSE, no new buttons are present. + */ +SMALLINT FindNewSHA(int portnum, uchar* devAN, SMALLINT resetList) +{ + uchar ROM[8]; + uchar tempList[MAX_SHA_IBUTTONS] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; + int tempIndex = 0, i; + SMALLINT hasDevices = TRUE, completeList = FALSE; + + /* force back to standard speed */ + if(MODE_NORMAL != owSpeed(portnum,MODE_NORMAL)) + { + OWERROR(OWERROR_LEVEL_FAILED); + return FALSE; + } + + in_overdrive[portnum&0x0FF] = FALSE; + + /* get first device in list with the specified family */ + if(needsFirst || resetList) + { + hasDevices = owFirst(portnum, TRUE, FALSE); + completeList = TRUE; + if(resetList) + listIndex = 0; + } + else + { + hasDevices = owNext(portnum, TRUE, FALSE); + } + + if(hasDevices) + { + do + { + /* verify correct device type */ + owSerialNum(portnum, ROM, TRUE); + tempList[tempIndex++] = ROM[7]; + + /* compare crc to complete list of ROMs */ + for(i=0; i0 && offset<17) + start += offset; + + /* set the serial number */ + owSerialNum(copr->portnum, copr->devAN, FALSE); + + OWASSERT( EraseScratchpadSHA18(copr->portnum, addr, FALSE), + OWERROR_ERASE_SCRATCHPAD_FAILED, FALSE ); + + OWASSERT( SHAFunction18(copr->portnum, SHA_COMPUTE_CHALLENGE, addr, TRUE), + OWERROR_SHA_FUNCTION_FAILED, FALSE ); + + OWASSERT( ReadScratchpadSHA18(copr->portnum, &addr, &es, scratchpad, TRUE), + OWERROR_READ_SCRATCHPAD_FAILED, FALSE ); + + memcpy(chlg,&scratchpad[start],3); + + return TRUE; +} + +/*------------------------------------------------------------------------- + * Answers a random challenge by performing an authenticated read of the + * user's account information. + * + * 'user' - Structure for holding user token information. + * 'chlg' - 3-byte buffer of challenge data. + * + * Return: the value of the write cycle counter for the account page. + * or -1 if there is an error + */ +#if 0 +int AnswerChallenge(SHAUser* user, uchar* chlg) +{ + int addr = user->accountPageNumber << 5; + + user->writeCycleCounter = -1; + memcpy(&user->accountFile[20], chlg, 3); + + /* set the serial number */ + owSerialNum(user->portnum, user->devAN, FALSE); + + if(user->devAN[0]==0x18) + { + /* for the DS1963S */ + OWASSERT( EraseScratchpadSHA18(user->portnum, addr, FALSE), + OWERROR_ERASE_SCRATCHPAD_FAILED, -1 ); + + OWASSERT( WriteScratchpadSHA18(user->portnum, addr, + user->accountFile, 32, + TRUE), + OWERROR_WRITE_SCRATCHPAD_FAILED, -1 ); + + user->writeCycleCounter = + ReadAuthPageSHA18(user->portnum, + user->accountPageNumber, + user->accountFile, + user->responseMAC, TRUE); + } + else if(user->devAN[0]==0x33||user->devAN[0]==0xB3) + { + /* for the DS1961S */ + OWASSERT( WriteScratchpadSHA33(user->portnum, addr, + &user->accountFile[16], + FALSE), + OWERROR_WRITE_SCRATCHPAD_FAILED, -1 ); + + user->writeCycleCounter = + ReadAuthPageSHA33(user->portnum, + user->accountPageNumber, + user->accountFile, + user->responseMAC, TRUE); + } + return user->writeCycleCounter; +} +#endif + +/*------------------------------------------------------------------------- + * Verifies the authentication response of a user token. + * + * 'copr' - Structure for holding coprocessor information. + * 'user' - Structure for holding user token information. + * 'chlg' - 3-byte buffer of challenge data. + * 'doBind' - if true, the user's unique secret is recreated on the + * coprocessor. If this function is called multiple times, + * it is acceptable to skip the bind for all calls after + * the first on the same user token. + * + * Return: If TRUE, the user's authentication response matched exactly the + * signature generated by the coprocessor. + * If FALSE, an error occurred or the signature did not match. + */ +SMALLINT VerifyAuthResponse(SHACopr* copr, SHAUser* user, + uchar* chlg, SMALLINT doBind) +{ + int addr = copr->wspcPageNumber << 5; + int wcc = user->writeCycleCounter; + uchar sign_cmd; + uchar scratchpad[32]; + uchar fullBindCode[15]; + + memset(scratchpad, 0x00, 32); + memset(fullBindCode, 0x0FF, 15); + + /* format the bind code properly */ + if(user->devAN[0]==0x18) + { + /* Format for DS1963S */ + memcpy(fullBindCode, copr->bindCode, 4); + memcpy(&fullBindCode[12], &(copr->bindCode[4]), 3); + /* use ValidateDataPage command */ + sign_cmd = SHA_VALIDATE_DATA_PAGE; + /* copy wcc LSB first */ + if(!IntToBytes(&scratchpad[8], 4, wcc)) + OWERROR(OWERROR_NO_ERROR_SET); + } + else if(user->devAN[0]==0x33||user->devAN[0]==0xB3) + { + /* Leave bindCode FF for DS1961S */ + /* Use AuthenticateHost command */ + sign_cmd = SHA_AUTHENTICATE_HOST; + /* the user doesn't have a write cycle counter */ + memset(&scratchpad[8], 0x0FF, 4); + } + else + { + OWERROR(OWERROR_WRONG_TYPE); + return FALSE; + } + + /* the pagenumber */ + fullBindCode[4] = (uchar)user->accountPageNumber; + /* and 7 bytes of the address of current device */ + memcpy(&fullBindCode[5], user->devAN, 7); + + /* get the user address and page num from fullBindCode */ + memcpy(&scratchpad[12], &fullBindCode[4], 8); + /* set the same challenge bytes */ + memcpy(&scratchpad[20], chlg, 3); + + /* set the serial number to that of the coprocessor */ + owSerialNum(copr->portnum, copr->devAN, FALSE); + + /* install user's unique secret on the wspc secret */ + if(doBind) + { + OWASSERT( BindSecretToiButton18(copr->portnum, + copr->authPageNumber, + copr->wspcPageNumber&7, + copr->bindData, fullBindCode, FALSE), + OWERROR_BIND_SECRET_FAILED, FALSE ); + if(user->devAN[0]==0x33||user->devAN[0]==0xB3) + { + /* also copy the resulting secret into secret location 0, to + * replace the signing secret. Necessary for producing the + * DS1961S's write-authorization MAC. + */ + OWASSERT( CopySecretSHA18(copr->portnum, 0), + OWERROR_COPY_SECRET_FAILED, FALSE); + } + } + + /* recreate the signature and verify */ + OWASSERT( WriteDataPageSHA18(copr->portnum, copr->wspcPageNumber, + user->accountFile, doBind), + OWERROR_WRITE_DATA_PAGE_FAILED, FALSE ); + + OWASSERT( WriteScratchpadSHA18(copr->portnum, addr, scratchpad, 32, TRUE), + OWERROR_WRITE_SCRATCHPAD_FAILED, FALSE ); + + OWASSERT( SHAFunction18(copr->portnum, sign_cmd, addr, TRUE), + OWERROR_SHA_FUNCTION_FAILED, FALSE ); + + OWASSERT( MatchScratchpadSHA18(copr->portnum, + user->responseMAC, TRUE), + OWERROR_MATCH_SCRATCHPAD_FAILED, FALSE ); + + return TRUE; +} + +/*------------------------------------------------------------------------- + * Creates a data signature for the given data buffer using the hardware + * coprocessor. + * + * 'copr' - Structure for holding coprocessor information. + * 'data' - data written to the data page to sign + * 'scratchpad' - data written to the scratchpad to sign + * 'signature' - data buffer which is either holding the signature that + * must match exactly what is generated on the coprocessor + * -or- will hold the resulting signature created by the + * coprocessor. + * 'readSignature' - implies whether or not the signature buffer + * receives the contents of the scratchpad or is used to + * match the contents of the scratchpad. If true, + * scratchpad contents are read into the signature buffer. + * + * Return: If TRUE, the user's authentication response matched exactly the + * signature generated by the coprocessor or the signature was + * successfully copied into the return buffer. + * If FALSE, an error occurred or the signature did not match. + */ +SMALLINT CreateDataSignature(SHACopr* copr, uchar* data, + uchar* scratchpad, uchar* signature, + SMALLINT readSignature) +{ + int addr = copr->signPageNumber << 5; + + /* set the serial number to that of the coprocessor */ + owSerialNum(copr->portnum, copr->devAN, FALSE); + + OWASSERT( WriteDataPageSHA18(copr->portnum, copr->signPageNumber, + data, FALSE), + OWERROR_WRITE_DATA_PAGE_FAILED, FALSE ); + + OWASSERT( WriteScratchpadSHA18(copr->portnum, addr, + scratchpad, 32, TRUE), + OWERROR_WRITE_SCRATCHPAD_FAILED, FALSE ); + + OWASSERT( SHAFunction18(copr->portnum, SHA_SIGN_DATA_PAGE, + addr, TRUE), + OWERROR_SHA_FUNCTION_FAILED, FALSE ); + + if(readSignature) + { + OWASSERT( ReadScratchpadSHA18(copr->portnum, 0, 0, + scratchpad, TRUE), + OWERROR_READ_SCRATCHPAD_FAILED, FALSE ); + } + else + { + OWASSERT( MatchScratchpadSHA18(copr->portnum, + signature, TRUE), + OWERROR_MATCH_SCRATCHPAD_FAILED, FALSE ); + } + + memcpy(signature, &scratchpad[8], 20); + + return TRUE; +} + + +/*------------------------------------------------------------------------- + * Decipher the variable Val into a 'len' byte array to set + * LSB First + */ +SMALLINT IntToBytes(uchar* byteArray, int len, unsigned int val) +{ + int i = 0; + for (; i>= 8; + } + + if(val==0) + return TRUE; + else + return FALSE; +} + +/*------------------------------------------------------------------------- + * Decipher the range 'len' of the byte array to an integer + * LSB First + */ +int BytesToInt(uchar* byteArray, int len) +{ + unsigned int val = 0; + int i = (len - 1); + /* Concatanate the byte array into one variable. */ + for (; i >= 0; i--) + { + val <<= 8; + val |= (byteArray[i] & 0x00FF); + } + return val; +} diff --git a/src/plugins/pro1_data_zip/ow/shaib.h b/src/plugins/pro1_data_zip/ow/shaib.h new file mode 100644 index 0000000..6df4301 --- /dev/null +++ b/src/plugins/pro1_data_zip/ow/shaib.h @@ -0,0 +1,250 @@ +/* shaib.h */ + +#ifndef SHAIBUTTON_H +#define SHAIBUTTON_H + +/* for ANSI memory commands - memcpy,memcmp,memset */ +#include +#include +#include "ownet.h" +#include "owfile.h" + +/************************************************************************* + * DS1963S SHA iButton commands + *************************************************************************/ +#define SHA_COMPUTE_FIRST_SECRET 0x0F +#define SHA_COMPUTE_NEXT_SECRET 0xF0 +#define SHA_VALIDATE_DATA_PAGE 0x3C +#define SHA_SIGN_DATA_PAGE 0xC3 +#define SHA_COMPUTE_CHALLENGE 0xCC +#define SHA_AUTHENTICATE_HOST 0xAA +#define CMD_READ_MEMORY 0xF0 +#define CMD_MATCH_SCRATCHPAD 0x3C +#define CMD_WRITE_SCRATCHPAD 0x0F +#define CMD_READ_SCRATCHPAD 0xAA +#define CMD_ERASE_SCRATCHPAD 0xC3 +#define CMD_COPY_SCRATCHPAD 0x55 +#define CMD_READ_AUTH_PAGE 0xA5 +#define CMD_COMPUTE_SHA 0x33 +#define ROM_CMD_SKIP 0x3C +#define ROM_CMD_RESUME 0xA5 + +/************************************************************************* + * DS1961S SHA iButton commands - rest are shared with above + *************************************************************************/ +#define SHA33_LOAD_FIRST_SECRET 0x5A +#define SHA33_COMPUTE_NEXT_SECRET 0x33 +#define SHA33_REFRESH_SCRATCHPAD 0xA3 + +/************************************************************************* + * other constants + *************************************************************************/ +#define SHA_FAMILY_CODE 0x18 +#define SHA33_FAMILY_CODE 0x33 +/* maximum number of buttons to track on the port */ +#define MAX_SHA_IBUTTONS 16 + +#define SHACoprFilename "shacopr.cnf" + +/************************************************************************* + * SHA Device Structures + *************************************************************************/ + +/* struct SHACopr + * Holds all information pertinent to SHA coprocessors, as + * well as all of the system parameters for this account + * transaction system. + */ +typedef struct +{ + /* portnum and address of the device */ + int portnum; + uchar devAN[8]; + + /* name of the account file stored on the user token */ + uchar serviceFilename[5]; + /* memory page used for signing certificate data (0 or 8) */ + uchar signPageNumber; + /* memory page used for storing master authentication secret + * and recreating user's unique secret + */ + uchar authPageNumber; + /* memory page used for storing user's unique secret + * and verifying the user's authentication response + */ + uchar wspcPageNumber; + /* version number of the system */ + uchar versionNumber; + /* Binding information for producing unique secrets */ + uchar bindCode[7]; + uchar bindData[32]; + /* challenge and signature used when signing account data */ + uchar signChlg[3]; + uchar initSignature[20]; + /* name of the transaction system provider */ + uchar* providerName; /* variable length */ + /* any other pertinent information */ + uchar* auxilliaryData; /* variable length */ + /* encryption code, used to specify additional encryption */ + uchar encCode; + /* indicates that the master authentication secret was + * padded to match the secret of a DS1961S + */ + uchar ds1961Scompatible; + +} SHACopr; + +/* struct SHAUser + * Holds all information pertinent to SHA user tokens. + * Maintains state between routines for verifying the + * user's authentication response, the account signature, + * and updating the account data. + */ +typedef struct +{ + /* portnum and address of the device */ + int portnum; + uchar devAN[8]; + + /* page the user's account file is stored on */ + uchar accountPageNumber; + /* Write cycle counter for account page */ + int writeCycleCounter; + /* MAC from Read Authenticated Page command */ + uchar responseMAC[20]; + + /* 32-byte account file */ + uchar accountFile[32]; + +} SHAUser; + +/* struct DebitFile + * Holds user token account data. Byte-ordering + * matters, so that this is a valid certificate + * as specified by Application Note 151. + */ +typedef struct +{ + uchar fileLength; + uchar dataTypeCode; + uchar signature[20]; + uchar convFactor[2]; + uchar balanceBytes[3]; + uchar transID[2]; + uchar contPtr; + uchar crc16[2]; + +} DebitFile; + +/* struct DebitFile33 + * Holds user token account data for DS1961S. + * Usese Double octa-byte scheme for dual money + * bytes and a pointer to the valid record. + */ +typedef struct +{ + /* header */ + uchar fileLength; + uchar dataTypeCode; + uchar convFactor[2]; + /* dont cares */ + uchar dontCareBytes1[4]; + /* record A */ + uchar balanceBytes_A[3]; + uchar transID_A[2]; + uchar contPtr_A; + uchar crc16_A[2]; + /* record B */ + uchar balanceBytes_B[3]; + uchar transID_B[2]; + uchar contPtr_B; + uchar crc16_B[2]; + /* dont cares */ + uchar dontCareBytes2[8]; + +} DebitFile33; + +/* file length used to point at Record A */ +#define RECORD_A_LENGTH 13 +/* file length used to point at Record B */ +#define RECORD_B_LENGTH 21 + + +/************************************************************************* + * DS1963S Low-level Functions - defined in sha18.c + *************************************************************************/ + +/* General I/O */ +extern SMALLINT CopySecretSHA18(int portnum, SMALLINT secretnum); +extern SMALLINT ReadScratchpadSHA18(int portnum, int* address, + uchar* es, uchar* data, + SMALLINT resume); +extern SMALLINT WriteScratchpadSHA18(int portnum, int address, + const uchar *data, SMALLINT data_len, + SMALLINT resume); +extern SMALLINT CopyScratchpadSHA18(int portnum, int address, + SMALLINT len, SMALLINT resume); +extern SMALLINT MatchScratchpadSHA18(int portnum, uchar* data, + SMALLINT resume); +extern SMALLINT EraseScratchpadSHA18(int portnum, int address, + SMALLINT resume); +extern int ReadAuthPageSHA18(int portnum, SMALLINT pagenum, uchar* data, + uchar* sign, SMALLINT resume); +extern SMALLINT ReadMemoryPageSHA18(int portnum, SMALLINT pagenum, uchar* data, + SMALLINT resume); +extern SMALLINT WriteDataPageSHA18(int portnum, SMALLINT pagenum, + uchar* data, SMALLINT resume); +extern SMALLINT SHAFunction18(int portnum, uchar control_byte, + int address, SMALLINT resume); +/* Secret Installation */ +extern SMALLINT InstallSystemSecret18(int portnum, SMALLINT pagenum, + SMALLINT secretnum, uchar* secret, + int secret_length, SMALLINT resume); +extern SMALLINT BindSecretToiButton18(int portnum, SMALLINT pagenum, + SMALLINT secretnum, + uchar* bindData, uchar* bindCode, + SMALLINT resume); +/************************************************************************/ + + +/* General Util */ +extern void ReformatSecretFor1961S(uchar* auth_secret, int secret_length); +extern void ComputeSHAVM(uchar* MT, long* hash); +extern void HashToMAC(long* hash, uchar* MAC); +/************************************************************************/ + +/************************************************************************* + * Protocol-Level Functions - defined in shaibutton.c + *************************************************************************/ + +/* Finding and accessing SHA iButtons */ +extern SMALLINT SelectSHA(int portnum); +extern SMALLINT FindNewSHA(int portnum, uchar* devAN, SMALLINT forceFirst); +/* extern SMALLINT FindUserSHA(SHAUser* user, FileEntry* fe, SMALLINT doBlocking); */ +/* extern SMALLINT FindCoprSHA(SHACopr* copr, FileEntry* fe); */ +extern int GetCoprFromRawData(SHACopr* copr, uchar* raw, int len); +/* General Protocol functions for 1963S */ +extern SMALLINT CreateChallenge(SHACopr* copr, SMALLINT pageNum, + uchar* chlg, SMALLINT offset); +/* extern int AnswerChallenge(SHAUser* user, uchar* chlg); */ +extern SMALLINT VerifyAuthResponse(SHACopr* copr, SHAUser* user, + uchar* chlg, SMALLINT doBind); +extern SMALLINT CreateDataSignature(SHACopr* copr, uchar* data, + uchar* scratchpad, uchar* signature, + SMALLINT readSignature); +/* Useful utility functions */ +extern SMALLINT IntToBytes(uchar* byteArray, int len, unsigned int val); +extern int BytesToInt(uchar* byteArray, int len); +/************************************************************************/ + +/************************************************************************/ + +/* Global - defined in shaibutton.c */ +extern SMALLINT in_overdrive[MAX_PORTNUM]; +/************************************************************************/ + +extern void PrintHexLabeled(char* label,uchar* buffer, int cnt); + +extern void ReadChars(uchar* buffer, int len); + +#endif /* SHAIBUTTON_H */ diff --git a/src/plugins/pro1_data_zip/pro1_data_zip.c b/src/plugins/pro1_data_zip/pro1_data_zip.c new file mode 100644 index 0000000..65bd0d6 --- /dev/null +++ b/src/plugins/pro1_data_zip/pro1_data_zip.c @@ -0,0 +1,442 @@ +/** + * vim: set et sw=4 ts=4: + * pro1_data_zip: add transparent encryption to prior decrypted data + * zips for Pump Pro 1 + */ +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef WIN32 +#define PATH_MAX 4096 +#else +#include +#endif +#include +#include "aes.h" +#include "dongle.h" +#include "sig.h" +#include "enc_zip_file.h" +#include "pro1_data_zip.h" +#include "PIUTools_SDK.h" +#include "PIUTools_Debug.h" +#include "util.h" + +typedef int (*open_func_t)(const char *, int, ...); +static open_func_t next_open; +typedef ssize_t (*read_func_t)(int, void *, size_t); +static read_func_t next_read; +typedef int (*lseek_func_t)(int, off_t, int); +static lseek_func_t next_lseek; +typedef int (*close_func_t)(int); +static close_func_t next_close; + +static char data_zip_dir[PATH_MAX]; +static zip_enc_context *head = NULL, *tail = NULL; + +zip_enc_context *create_new_context(const char *path, int fd); + +// ugly routine yanked from sm-ac-tools +void saltHash(uint8_t *salted, const uint8_t salt[16], int addition) { + int cSalt = 0, cSalt2 = 0, cSalt3 = 0; + + cSalt = (int)(salt[0]); + cSalt2 = (int)(salt[1]); + cSalt3 = (int)(salt[9]); + cSalt += addition; + salted[0] = (char)cSalt; + cSalt >>= 8; + cSalt += cSalt2; + cSalt2 = (int)(salt[2]); + salted[1] = (char)cSalt; + cSalt >>= 8; + cSalt += cSalt2; + cSalt2 = (int)(salt[3]); + salted[2] = (char)cSalt; + cSalt >>= 8; + cSalt2 += cSalt; + cSalt = (int)(salt[4]); + salted[3] = (char)cSalt2; + cSalt2 >>= 8; + cSalt2 += cSalt; + cSalt = (int)(salt[5]); + salted[4] = (char)cSalt2; + cSalt2 >>= 8; + cSalt += cSalt2; + cSalt2 = (int)(salt[6]); + salted[5] = (char)cSalt; + cSalt >>= 8; + cSalt2 += cSalt; + cSalt = (int)(salt[7]); + salted[6] = (char)cSalt2; + cSalt2 >>= 8; + cSalt += cSalt2; + cSalt2 = (int)(salt[8]); + salted[7] = (char)cSalt; + cSalt >>= 8; + cSalt2 += cSalt; + cSalt = (int)(salt[10]); + salted[8] = (char)cSalt2; + cSalt2 >>= 8; + cSalt3 += cSalt2; + cSalt2 = (int)(salt[11]); + salted[9] = (char)cSalt3; + cSalt3 >>= 8; + cSalt += cSalt3; + salted[10] = cSalt; + cSalt >>= 8; + cSalt += cSalt2; + cSalt2 = (int)(salt[12]); + salted[11] = cSalt; + cSalt >>= 8; + cSalt += cSalt2; + cSalt2 = (int)(salt[13]); + salted[12] = cSalt; + cSalt >>= 8; + cSalt += cSalt2; + cSalt2 = (int)(salt[14]); + salted[13] = cSalt; + cSalt >>= 8; + cSalt2 += cSalt; + cSalt = (int)(salt[15]); + salted[14] = cSalt2; + cSalt2 >>= 8; + cSalt += cSalt2; + salted[15] = cSalt; +} + +static char *verify_block_plaintext = "<fd == fd) { + return stl; + } + stl = stl->next; + } + return NULL; +} + +zip_enc_context *find_context_by_path(const char *path) { + zip_enc_context *stl = head; + while (stl != NULL) { + if (strncmp(path, stl->pathname, strlen(path)) == 0) { + return stl; + } + stl = stl->next; + } + return NULL; +} + +int is_data_zip_file(const char *path) { + /* 1 = data zip, 0 = not */ + char fullpath[PATH_MAX+1]; + if (data_zip_dir == NULL) { + return 0; + } + if (realpath(path, fullpath) == NULL) { + fprintf(stderr, "Cannot resolve full path for %s: %s\n", path, strerror(errno)); + return 0; + } + if (strncmp(path+strlen(path)-4, ".zip", 4) != 0) { + return 0; + } + return (strstr(fullpath, data_zip_dir) == fullpath) ? 1 : 0; +} + +/* determines if it's a data zip file and registers a context with it */ +int pro1_data_zip_open(const char *path, int flags, ...) { + if (is_data_zip_file(path)) { + zip_enc_context *zip_ctx = find_context_by_path(path); + int fd = next_open(path, flags); + if (fd == -1) { + perror("open()"); + return -1; + } + if (zip_ctx == NULL) { + DBG_printf("%s: opening new data zip file (%s)\n", __FUNCTION__, path); + zip_ctx = create_new_context(path, fd); + if (zip_ctx == NULL) { + fprintf(stderr, "[%s:%d] Could not create new data zip context for %s\n", __FILE__, __LINE__, path); + errno = EACCES; + return -1; + } + } else { + DBG_printf("%s: opening prior opened data zip file (%s)\n", __FUNCTION__, path); + zip_ctx->fd = fd; + } + zip_ctx->pos = 0; + return fd; + } else { + return next_open(path, flags); + } +} + +/* cheeso way of adding unsigned integer to_add to a 128-bit unsigned integer + * represented in little-endian format by the bytes add_to */ +void uint128_le_add(uint8_t add_to[16], const unsigned int to_add) { + int carry = 0; + for (int j = 0; j < 16; j++) { + if (j > 3) { + if (add_to[j] == 255 && carry == 1) { + add_to[j] = 0; + } else { + carry = 0; + } + } else { + uint8_t segmented_addition = (to_add & (0xff << ((j)*8))) >> ((j)*8); + uint8_t oldcarry = add_to[j]; + + add_to[j] += segmented_addition + carry; + if ((int)segmented_addition + (int)oldcarry > 255) { + carry = 1; + } else { + carry = 0; + } + } + } +} + +ssize_t pro1_data_zip_read(int fd, void *buf, size_t count) { + // fool the client into reading additional data before or after the + // file itself such as the crypt header or file signature + + size_t remaining = count; // how much of the buffer is remaining + // position in our fake file where the encrypted data starts + off_t data_start = sizeof(enc_zip_file_header), + // position in our fake file where the signature starts + sig_start, sig_end; + ssize_t got = 0; + zip_enc_context *zip_ctx = find_context_by_fd(fd); + if (remaining == 0 || zip_ctx == NULL) { + return next_read(fd, buf, count); + } + sig_start = data_start + zip_ctx->header->file_size; + // the encrypted data contents have to be a multiple of 16 + if (zip_ctx->header->file_size % 16 > 0) { + sig_start += 16 - (zip_ctx->header->file_size % 16); + } + sig_end = sig_start + sizeof(zip_ctx->sig); + + if (zip_ctx->pos < data_start) { + DBG_printf("(pos:%d) reading out header\n", zip_ctx->pos); + // read header first if applicable + size_t header_count = min(remaining, data_start-zip_ctx->pos); + memcpy(buf, (void *)(zip_ctx->header)+zip_ctx->pos, header_count); + remaining -= header_count; + zip_ctx->pos += header_count; + got += header_count; + } + if (zip_ctx->pos < sig_start && remaining > 0) { + //DBG_printf("(pos:%d) reading out data\n", zip_ctx->pos); + // how much data we're going to process, clamped to how much data + // is actually available + size_t encrypted_data_remaining = min(remaining, sig_start-zip_ctx->pos); + size_t plaintext_remaining = (data_start + zip_ctx->header->file_size) - zip_ctx->pos; + // the position in the data section of our "container" file + off_t encrypted_data_pos = zip_ctx->pos - data_start; + uint8_t salt_copy[16], decbuf[16], dsalted[16]; + int skip_bytes_in_first_block = encrypted_data_pos % 16; + unsigned int block_start = encrypted_data_pos / 16; + // prepare salt + memcpy(salt_copy, zip_ctx->header->salt, sizeof salt_copy); + uint128_le_add(salt_copy, block_start); + + next_lseek(fd, block_start * 16, SEEK_SET); + + // encrypt contained data + while (encrypted_data_remaining > 0) { + int crypt_expected = min(16, plaintext_remaining); + int crypt_got = next_read(fd, decbuf, crypt_expected); + if (crypt_got == -1) { + perror("read()"); + return -1; + } + if (crypt_got != crypt_expected) { + // TODO: should be able to handle such a scenario + fprintf(stderr, "read(): expected %d, got %d\n", crypt_expected, crypt_got); + return -1; + } + plaintext_remaining -= crypt_expected; + + memcpy(dsalted, salt_copy, sizeof dsalted); + AES_ECB_encrypt(&zip_ctx->aes_ctx, dsalted); + uint128_le_add(salt_copy, 1); + int bytes_to_process = min(encrypted_data_remaining, 16); + for (int j = skip_bytes_in_first_block; j < bytes_to_process; j++) { + *((uint8_t *)(buf+got)) = dsalted[j] ^ decbuf[j]; + got++; + remaining--; + encrypted_data_remaining--; + zip_ctx->pos++; + } + skip_bytes_in_first_block = 0; + } + DBG_printf("%s: done reading out encrypted data for %d (%s)\n", __FUNCTION__, fd, zip_ctx->pathname); + } + if (zip_ctx->pos >= sig_start && remaining > 0) { + // read signature + size_t sig_available = sig_end - zip_ctx->pos; + size_t read_from_sig = min(sig_available, min(remaining, sizeof(zip_ctx->sig))); + DBG_printf("(pos:%d) reading out sig (read_from_sig:%d)\n", zip_ctx->pos, read_from_sig); + memcpy(buf+got, (void *)(&zip_ctx->sig[zip_ctx->pos - sig_start]), read_from_sig); + zip_ctx->pos += read_from_sig; + got += read_from_sig; + } + return got; +} + +int pro1_data_zip_lseek(int fd, off_t offset, int whence) { + zip_enc_context *zip_ctx = find_context_by_fd(fd); + if (zip_ctx == NULL) { + return next_lseek(fd, offset, whence); + } + + off_t new_offset = 0; + size_t zip_size = sizeof(enc_zip_file_header) + zip_ctx->header->file_size + sizeof(zip_ctx->sig); + if (zip_ctx->header->file_size % 16 > 0) { + zip_size += (16 - (zip_ctx->header->file_size % 16)); + } + + switch (whence) { + case SEEK_SET: + new_offset = offset; + break; + case SEEK_CUR: + new_offset = zip_ctx->pos + offset; + break; + case SEEK_END: + new_offset = zip_size + offset; + break; + } + + if (new_offset > zip_size) { + errno = EOVERFLOW; + return -1; + } + + zip_ctx->pos = new_offset; + return zip_ctx->pos; +} + +int pro1_data_zip_close(int fd) { + /* scrub the fd from the list */ + zip_enc_context *zip_ctx = find_context_by_fd(fd); + if (zip_ctx != NULL) { + zip_ctx->fd = 0; + } + return next_close(fd); +} + +zip_enc_context *create_new_context(const char *path, int fd) { + uint8_t salted[16]; + + DBG_printf("pro1_data_zip: Creating new context for %s\n", path); + zip_enc_context *ctx = (zip_enc_context *)malloc(sizeof(zip_enc_context)); + ctx->fd = fd; + ctx->pos = 0; + ctx->pathname = (char *)malloc(strlen(path)+1); + ctx->pathname[strlen(path)] = 0x0; + strncpy(ctx->pathname, path, strlen(path)); + ctx->header = generate_header(fd); + + // derive key and verify block + if (derive_aes_key_from_ds1963s(ctx->header, ctx->aes_key) != 0) { + fprintf(stderr, "failed to derive AES key from ds1963s\n"); + free(ctx->pathname); + free(ctx); + return NULL; + } + saltHash(salted, ctx->header->salt, 0x123456); + AES_init_ctx(&ctx->aes_ctx, ctx->aes_key); + AES_ECB_encrypt(&ctx->aes_ctx, salted); + for (int i = 0; i < 16; i++) { + ctx->header->verify_block[i] = verify_block_plaintext[i] ^ salted[i]; + } + + ctx->next = NULL; + if (head == NULL) { + head = ctx; + tail = head; + } else { + tail->next = ctx; + tail = tail->next; + } + + if (generate_file_signature(ctx, fd, pro1_data_zip_read, pro1_data_zip_lseek, ctx->sig) != 0) { + fprintf(stderr, "%s: failed to generate file signature!\n", path); + free(ctx->pathname); + free(ctx); + return NULL; + } + memcpy(&ctx->sig[sizeof(ctx->sig)-5], "SRSLY", 5); + + return ctx; +} + +typedef void *(*string_cons_hook_func)(void *, const char*, unsigned int, void *); +string_cons_hook_func next_string_cons; + +static int pubkey_intercepted = 0; + +// set to 1 if the module should not intercept fcntl functions +static int no_handle_files = 0; + +/** + * string constructor hook + */ +void *pro1_data_zip_string_cons_hook(void *this, const char *str, unsigned int size, void *alloc) { + if (size == sizeof(their_pubkey) && pubkey_intercepted == 0) { + if (memcmp(str, their_pubkey, sizeof(their_pubkey)) == 0) { + DBG_printf("[%s:%d] injecting our own public key (0x%08x)\n", __FILE__, __LINE__, (unsigned int)str); + return next_string_cons(this, our_pubkey, size, alloc); + } + pubkey_intercepted = 1; + } + return next_string_cons(this, str, size, alloc); +} + +static HookEntry entries[] = { + HOOK_ENTRY(HOOK_TYPE_IMPORT, HOOK_TARGET_BASE_EXECUTABLE, "libc.so.6", "open", pro1_data_zip_open, &next_open, 1), + HOOK_ENTRY(HOOK_TYPE_IMPORT, HOOK_TARGET_BASE_EXECUTABLE, "libc.so.6", "read", pro1_data_zip_read, &next_read, 1), + HOOK_ENTRY(HOOK_TYPE_IMPORT, HOOK_TARGET_BASE_EXECUTABLE, "libc.so.6", "lseek", pro1_data_zip_lseek, &next_lseek, 1), + HOOK_ENTRY(HOOK_TYPE_IMPORT, HOOK_TARGET_BASE_EXECUTABLE, "libc.so.6", "close", pro1_data_zip_close, &next_close, 1), + /* + HOOK_ENTRY(HOOK_TYPE_INLINE, HOOK_TARGET_BASE_EXECUTABLE, "libpthread.so.0", "open", pro1_data_zip_open, &next_open, 1), + HOOK_ENTRY(HOOK_TYPE_INLINE, HOOK_TARGET_BASE_EXECUTABLE, "libpthread.so.0", "read", pro1_data_zip_read, &next_read, 1), + HOOK_ENTRY(HOOK_TYPE_INLINE, HOOK_TARGET_BASE_EXECUTABLE, "libpthread.so.0", "lseek", pro1_data_zip_lseek, &next_lseek, 1), + HOOK_ENTRY(HOOK_TYPE_INLINE, HOOK_TARGET_BASE_EXECUTABLE, "libpthread.so.0", "close", pro1_data_zip_close, &next_close, 1), + */ + + // std::string::string(char const*,uint,std::allocator const&) + HOOK_ENTRY(HOOK_TYPE_IMPORT, HOOK_TARGET_BASE_EXECUTABLE, "libstdc++.so.5", "_ZNSsC2EPKcjRKSaIcE", pro1_data_zip_string_cons_hook, &next_string_cons, 1), + {} +}; + +static HookEntry entries_no_handle_files[] = { + // std::string::string(char const*,uint,std::allocator const&) + HOOK_ENTRY(HOOK_TYPE_IMPORT, HOOK_TARGET_BASE_EXECUTABLE, "libstdc++.so.5", "_ZNSsC2EPKcjRKSaIcE", pro1_data_zip_string_cons_hook, &next_string_cons, 1), + {} +}; + +static HookConfigEntry plugin_config[] = { + CONFIG_ENTRY("PRO1_DATA_ZIP","data_zip_dir",CONFIG_TYPE_STRING,data_zip_dir,sizeof(data_zip_dir)), + CONFIG_ENTRY("PRO1_DATA_ZIP","no_handle_files",CONFIG_TYPE_INT,&no_handle_files,sizeof(no_handle_files)), + {} +}; + +const PHookEntry plugin_init() { + PIUTools_Config_Read(plugin_config); + head = NULL; + tail = NULL; + if (no_handle_files != 0) { + return entries_no_handle_files; + } else { + return entries; + } +} diff --git a/src/plugins/pro1_data_zip/pro1_data_zip.h b/src/plugins/pro1_data_zip/pro1_data_zip.h new file mode 100644 index 0000000..1d566bc --- /dev/null +++ b/src/plugins/pro1_data_zip/pro1_data_zip.h @@ -0,0 +1,22 @@ +#pragma once +#include +#include "aes.h" +#include "enc_zip_file.h" + +/** + * bookkeeping for each opened file + */ +typedef struct zip_enc_context { + char *pathname; + int fd; + off_t pos; + uint8_t aes_key[24]; + struct AES_ctx aes_ctx; + enc_zip_file_header *header; + struct zip_enc_context *next; + // each data zip can have a signature field at the end + // that is created by a keypair internal to FiM. The public bits are + // hardcoded in the piu binary. This is followed by a magic "SRSLY" + // footer. + uint8_t sig[128+5]; +} zip_enc_context; diff --git a/src/plugins/pro1_data_zip/sig.c b/src/plugins/pro1_data_zip/sig.c new file mode 100644 index 0000000..4a3b528 --- /dev/null +++ b/src/plugins/pro1_data_zip/sig.c @@ -0,0 +1,194 @@ +#include +#include +#include +#include +#include "tommath.h" +#define LTM_DESC +#include "tomcrypt.h" +#include "PIUTools_SDK.h" +#include "pro1_data_zip.h" +#include "sig.h" +#include "util.h" + +//#define SIG_DEBUG +#undef SIG_DEBUG + +static rsa_key our_rsa_key; +static int key_imported = 0; +static int sprng_idx, sha1_idx; + +// the pubkey stored in the PIU Pro binary +const unsigned char their_pubkey[140] = { + 0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00, 0xb7, 0x0d, 0x2c, + 0xe1, 0xf3, 0xaf, 0x2b, 0xec, 0xfb, 0xe3, 0x00, 0x75, 0x42, + 0xbf, 0x9b, 0xf5, 0x85, 0x9f, 0xf0, 0x8f, 0x2c, 0x36, 0x2a, + 0xb6, 0x7c, 0x81, 0x78, 0x3d, 0x05, 0x7f, 0xc6, 0xec, 0xd3, + 0x34, 0xed, 0x31, 0x73, 0x0b, 0xa4, 0x81, 0x25, 0xa8, 0xe2, + 0x0f, 0x02, 0xce, 0xba, 0x82, 0x95, 0xb9, 0x5a, 0x49, 0xc7, + 0xe6, 0x6e, 0xb3, 0xe2, 0xcc, 0xae, 0x18, 0x7f, 0x0f, 0xde, + 0x5f, 0x03, 0x06, 0x00, 0x3d, 0xa5, 0x15, 0x6d, 0x7e, 0x0e, + 0x8a, 0x8b, 0xbf, 0x26, 0x26, 0xee, 0x2a, 0xd8, 0x45, 0xdc, + 0xd2, 0xba, 0xf0, 0x44, 0x13, 0x6e, 0xc6, 0xc3, 0x79, 0x57, + 0xfc, 0x14, 0x32, 0x01, 0x95, 0x66, 0xe5, 0x34, 0x9c, 0xc6, + 0x49, 0xf3, 0xb0, 0x81, 0x6e, 0x26, 0x64, 0xa9, 0x9d, 0x04, + 0xa2, 0x44, 0x3a, 0xde, 0x3b, 0x5e, 0xa4, 0x6e, 0xfd, 0x28, + 0x01, 0xd2, 0xd9, 0x61, 0x45, 0x02, 0x03, 0x01, 0x00, 0x01, +}; + +// our replacement pub/privkeys +const unsigned char our_pubkey[140] = { + 0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00, 0xbb, 0xed, 0xa6, 0x26, 0xec, 0xe7, 0xc3, 0x60, 0x07, + 0xe7, 0xab, 0xf4, 0x05, 0x2f, 0xde, 0x6b, 0x86, 0x92, 0x65, 0x57, 0xf8, 0x57, 0xf5, 0xb2, 0x8f, + 0xe1, 0x2b, 0x4f, 0x73, 0xb1, 0x4a, 0xf1, 0xf2, 0xcc, 0x7f, 0x49, 0xd1, 0xd2, 0x48, 0xf1, 0x29, + 0x73, 0x59, 0x5c, 0x5d, 0x4a, 0x4f, 0x0f, 0x29, 0x15, 0xa8, 0xea, 0x7c, 0x92, 0x59, 0xa9, 0x8a, + 0x64, 0x5f, 0xba, 0x5a, 0x40, 0x43, 0x1f, 0x2d, 0x63, 0x5a, 0xd9, 0x31, 0x60, 0xd5, 0xa2, 0xac, + 0x99, 0xa1, 0xc9, 0x40, 0xf8, 0x92, 0xe5, 0x12, 0xe7, 0xa4, 0xeb, 0xe6, 0x02, 0xb3, 0xef, 0x5c, + 0xa4, 0x7f, 0x8f, 0x7f, 0xc8, 0x6f, 0xbe, 0x48, 0xaf, 0x0b, 0x67, 0x87, 0xd6, 0x73, 0xd3, 0xe8, + 0xba, 0x1f, 0x01, 0xfe, 0x9f, 0x35, 0xfd, 0xc1, 0x38, 0x7d, 0x39, 0x10, 0xed, 0x07, 0x77, 0x02, + 0xca, 0xf3, 0x52, 0xec, 0x7b, 0x1c, 0x83, 0x02, 0x03, 0x01, 0x00, 0x01 +}; + +const unsigned char our_privkey[608] = { + 0x30, 0x82, 0x02, 0x5c, 0x02, 0x01, 0x00, 0x02, 0x81, 0x81, 0x00, 0xbb, 0xed, 0xa6, 0x26, 0xec, + 0xe7, 0xc3, 0x60, 0x07, 0xe7, 0xab, 0xf4, 0x05, 0x2f, 0xde, 0x6b, 0x86, 0x92, 0x65, 0x57, 0xf8, + 0x57, 0xf5, 0xb2, 0x8f, 0xe1, 0x2b, 0x4f, 0x73, 0xb1, 0x4a, 0xf1, 0xf2, 0xcc, 0x7f, 0x49, 0xd1, + 0xd2, 0x48, 0xf1, 0x29, 0x73, 0x59, 0x5c, 0x5d, 0x4a, 0x4f, 0x0f, 0x29, 0x15, 0xa8, 0xea, 0x7c, + 0x92, 0x59, 0xa9, 0x8a, 0x64, 0x5f, 0xba, 0x5a, 0x40, 0x43, 0x1f, 0x2d, 0x63, 0x5a, 0xd9, 0x31, + 0x60, 0xd5, 0xa2, 0xac, 0x99, 0xa1, 0xc9, 0x40, 0xf8, 0x92, 0xe5, 0x12, 0xe7, 0xa4, 0xeb, 0xe6, + 0x02, 0xb3, 0xef, 0x5c, 0xa4, 0x7f, 0x8f, 0x7f, 0xc8, 0x6f, 0xbe, 0x48, 0xaf, 0x0b, 0x67, 0x87, + 0xd6, 0x73, 0xd3, 0xe8, 0xba, 0x1f, 0x01, 0xfe, 0x9f, 0x35, 0xfd, 0xc1, 0x38, 0x7d, 0x39, 0x10, + 0xed, 0x07, 0x77, 0x02, 0xca, 0xf3, 0x52, 0xec, 0x7b, 0x1c, 0x83, 0x02, 0x03, 0x01, 0x00, 0x01, + 0x02, 0x81, 0x80, 0x35, 0x7a, 0x4b, 0xa9, 0x51, 0x0a, 0x24, 0xd1, 0x5b, 0x7e, 0x84, 0x32, 0xb5, + 0x15, 0x29, 0xa4, 0x8c, 0x8f, 0x75, 0x52, 0x62, 0xc3, 0xd9, 0x11, 0x9e, 0x9a, 0xf3, 0x61, 0xb1, + 0x28, 0xf7, 0x0c, 0x41, 0xcd, 0x0a, 0xbd, 0xdd, 0x7d, 0x0b, 0x2f, 0xc1, 0x5d, 0x67, 0x44, 0xfe, + 0xf1, 0x29, 0xed, 0x45, 0x02, 0x3a, 0x66, 0xbb, 0xdb, 0x43, 0xb3, 0x98, 0xc3, 0xb6, 0x70, 0x07, + 0xc5, 0xb8, 0xb3, 0x95, 0x20, 0x6c, 0x7c, 0xad, 0x75, 0x02, 0x00, 0xa9, 0x1a, 0xea, 0xc6, 0xe0, + 0xc0, 0x7f, 0x0e, 0xc1, 0x12, 0x05, 0xe7, 0xf1, 0x32, 0x0d, 0x5a, 0x1a, 0xa3, 0xa5, 0xec, 0xe5, + 0x80, 0x0c, 0x04, 0x3e, 0x7f, 0xfb, 0x0b, 0x49, 0xbe, 0x67, 0xef, 0x8a, 0x5e, 0x98, 0x7e, 0xa1, + 0xb4, 0x4f, 0x57, 0x3d, 0x1b, 0xe3, 0xe9, 0x33, 0x3f, 0x91, 0x0c, 0x14, 0x83, 0xbc, 0xf1, 0x8c, + 0x47, 0xbc, 0xa1, 0x02, 0x41, 0x00, 0xfa, 0x53, 0xe3, 0x8e, 0x78, 0x1d, 0xae, 0x89, 0x03, 0x9c, + 0x0e, 0x9b, 0xd4, 0x70, 0xa4, 0x8c, 0x01, 0x9c, 0x90, 0x66, 0x1c, 0xa7, 0xf4, 0x86, 0x3f, 0x57, + 0x1f, 0xc5, 0xc3, 0x83, 0xe9, 0x82, 0x62, 0xbd, 0x7f, 0xdf, 0xd4, 0xbf, 0x56, 0x1f, 0xfe, 0xa4, + 0x5a, 0x88, 0x68, 0x47, 0xbe, 0xd5, 0xe1, 0x21, 0xb3, 0xf7, 0xfb, 0x7f, 0xac, 0xe6, 0x9d, 0x7f, + 0x9b, 0x6d, 0xb9, 0x16, 0x2b, 0xe3, 0x02, 0x41, 0x00, 0xc0, 0x2f, 0xca, 0x92, 0x58, 0x37, 0xa6, + 0x6f, 0x83, 0x7b, 0x0d, 0xe0, 0xd3, 0xd0, 0x60, 0x9e, 0xfa, 0x19, 0x0d, 0x82, 0x35, 0x93, 0xd8, + 0x18, 0xa7, 0x80, 0x55, 0x9d, 0xa3, 0x84, 0xd2, 0x2a, 0xd0, 0x9a, 0x1a, 0xa1, 0x21, 0xaf, 0x72, + 0xac, 0x4f, 0xf6, 0xdb, 0x39, 0x64, 0x01, 0x81, 0xc5, 0xda, 0x28, 0x3f, 0x1a, 0xf9, 0xc1, 0xc5, + 0x2c, 0x0d, 0x16, 0x72, 0x80, 0x41, 0xc1, 0x6e, 0xe1, 0x02, 0x40, 0x49, 0x29, 0x4f, 0x6e, 0x8a, + 0x28, 0x92, 0xa4, 0x34, 0xcb, 0xdd, 0x71, 0x29, 0xcb, 0xaa, 0x2b, 0xc9, 0x24, 0xcb, 0x07, 0x2d, + 0x04, 0xe1, 0x70, 0x82, 0xfe, 0xa1, 0xa8, 0x99, 0x15, 0xea, 0x9f, 0x52, 0xe0, 0x73, 0x89, 0x25, + 0x92, 0xae, 0x47, 0x37, 0x93, 0x2d, 0x6a, 0x84, 0x9f, 0xc3, 0x64, 0x9b, 0x21, 0xd0, 0x89, 0x7f, + 0x95, 0xb7, 0x20, 0xc7, 0x93, 0x4e, 0x07, 0xe9, 0x7a, 0x53, 0x65, 0x02, 0x40, 0x6c, 0x89, 0x91, + 0x09, 0xdd, 0x30, 0x70, 0x9a, 0x81, 0xd2, 0xb9, 0x1f, 0xc3, 0xff, 0xe6, 0xd1, 0x61, 0xc5, 0x4c, + 0x4f, 0xc1, 0x1a, 0x61, 0xec, 0x6a, 0x8c, 0x9b, 0xcd, 0x8f, 0x4f, 0xaf, 0xb1, 0xe6, 0x65, 0x61, + 0xac, 0xa6, 0x6d, 0x83, 0x81, 0xb5, 0x17, 0x60, 0xef, 0xa4, 0x7f, 0x05, 0x5f, 0x4b, 0xb9, 0x77, + 0x0a, 0x31, 0x0b, 0x31, 0xe3, 0x92, 0xf0, 0x9e, 0x71, 0xb8, 0xb1, 0x19, 0x81, 0x02, 0x41, 0x00, + 0xad, 0x4f, 0x5f, 0x26, 0x06, 0x26, 0x3f, 0xdb, 0x17, 0x2d, 0xd4, 0x0a, 0xcd, 0xa0, 0x76, 0x9a, + 0xef, 0x84, 0x1b, 0x59, 0xf8, 0x7d, 0x3f, 0x6f, 0x5d, 0xbf, 0x76, 0x42, 0xff, 0xe8, 0x71, 0x45, + 0xcb, 0x6e, 0xb7, 0xbe, 0x87, 0x72, 0xd4, 0x2a, 0xbb, 0x9e, 0xd2, 0xc6, 0x61, 0xc4, 0xce, 0xfb, + 0xb4, 0xa9, 0x3c, 0x75, 0xac, 0xa3, 0x89, 0xdf, 0x34, 0x98, 0xa9, 0x29, 0x6b, 0x79, 0xca, 0xcb +}; + + +int generate_file_signature(zip_enc_context *ctx, int fd, + read_func_t read_func, lseek_func_t lseek_func, + uint8_t *out) { + // get file size (sans sig and footer) + off_t amt = lseek_func(fd, 0, SEEK_END) - 133; + DBG_printf("[sig] File size: %lu\n", amt); + lseek_func(fd, 0, SEEK_SET); + + // get double SHA1 of header+data + hash_state shactx, shactx2; + size_t got = 0, readsize = 0; + uint8_t buf[0x10000]; + uint8_t filehash[20], sha1result[20]; + int err; + off_t pos = 0; + + ltc_mp = ltm_desc; + if ((sprng_idx = register_prng(&sprng_desc)) == -1) { + fprintf(stderr, "Could not register SPRNG\n"); + return -1; + } + if ((sha1_idx = register_hash(&sha1_desc)) == -1) { + fprintf(stderr, "Could not register SHA1 hash descriptor\n"); + return -1; + } + + sha1_init(&shactx); + sha1_init(&shactx2); + long curpos = 0; + + while (pos < amt) { + curpos = lseek_func(fd, pos, SEEK_SET); + readsize = (amt < 0x10000) ? amt : 0x10000; + got = read_func(fd, buf, readsize); + if (got != readsize) { + fprintf(stderr, "%s: read_func(zip_fd) failed, got %d\n", __FUNCTION__, got); + return -1; + } + sha1_process(&shactx, buf, got); + DBG_printf("[pro1_data_zip:%s](%s) processed %d bytes at %lu(%lu)\n", __FUNCTION__, ctx->pathname, got, curpos, pos); + if (pos + got >= amt) { + break; + } + pos += 0x1000000; + if (pos + 0x10000 > amt) { + pos = amt - 0x10000; + } + } + + if ((err = sha1_done(&shactx, sha1result)) != CRYPT_OK) { + fprintf(stderr, "sha1_done failed: %s\n", error_to_string(err)); + return -1; + } + sha1_process(&shactx2, sha1result, 20); + if ((err = sha1_done(&shactx2, filehash)) != CRYPT_OK) { + fprintf(stderr, "sha1_done failed: %s\n", error_to_string(err)); + return -1; + } + + DBG_printf("%s hash1: %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n", + ctx->pathname, + sha1result[0], sha1result[1], sha1result[2], sha1result[3], sha1result[4], sha1result[5], + sha1result[6], sha1result[7], sha1result[8], sha1result[9], sha1result[10], sha1result[11], + sha1result[12], sha1result[13], sha1result[14], sha1result[15], sha1result[16], sha1result[17], + sha1result[18], sha1result[19]); + DBG_printf("%s hash2: %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n", + ctx->pathname, + filehash[0], filehash[1], filehash[2], filehash[3], filehash[4], filehash[5], + filehash[6], filehash[7], filehash[8], filehash[9], filehash[10], filehash[11], + filehash[12], filehash[13], filehash[14], filehash[15], filehash[16], filehash[17], + filehash[18], filehash[19]); + + if (key_imported == 0) { + if ((err = rsa_import(our_privkey, sizeof(our_privkey), &our_rsa_key)) != CRYPT_OK) { + fprintf(stderr, "Could not import RSA key: %s\n", error_to_string(err)); + return -1; + } + key_imported = 1; + } + + unsigned long sigout = 133; + + if ((err = rsa_sign_hash_ex(filehash, 20, ctx->sig, &sigout, LTC_PKCS_1_V1_5, NULL, sprng_idx, sha1_idx, 0, &our_rsa_key)) != CRYPT_OK) { + fprintf(stderr, "Could not sign hash: %s\n", error_to_string(err)); + return -1; + } + assert(sigout == 128); + +#ifdef SIG_DEBUG + char sig_outfile[64]; + sprintf(sig_outfile, "%s.sig", basename(ctx->pathname)); + FILE *sfd = fopen(sig_outfile, "wb"); + if (sfd == NULL) { + fprintf(stderr, "SIG_DEBUG: fopen(): %s\n", strerror(errno)); + } else { + fwrite(ctx->sig, 1, sigout, sfd); + fclose(sfd); + } +#endif + + return 0; +} diff --git a/src/plugins/pro1_data_zip/sig.h b/src/plugins/pro1_data_zip/sig.h new file mode 100644 index 0000000..20ee80b --- /dev/null +++ b/src/plugins/pro1_data_zip/sig.h @@ -0,0 +1,15 @@ +#ifndef _SIG_H_ +#define _SIG_H_ +#include "pro1_data_zip.h" +#include + +const unsigned char their_pubkey[140], our_pubkey[140], our_privkey[608]; + +typedef ssize_t (*read_func_t)(int, void *, size_t); +typedef int (*lseek_func_t)(int, off_t, int); + +int generate_file_signature(zip_enc_context *ctx, int fd, + read_func_t read_func, lseek_func_t lseek_func, + uint8_t *out); + +#endif /* _SIG_H_ */ diff --git a/src/plugins/pro1_data_zip/tools/.gitignore b/src/plugins/pro1_data_zip/tools/.gitignore new file mode 100644 index 0000000..f68f810 --- /dev/null +++ b/src/plugins/pro1_data_zip/tools/.gitignore @@ -0,0 +1,3 @@ +verify +resign +*.o diff --git a/src/plugins/pro1_data_zip/tools/Makefile b/src/plugins/pro1_data_zip/tools/Makefile new file mode 100644 index 0000000..112dcba --- /dev/null +++ b/src/plugins/pro1_data_zip/tools/Makefile @@ -0,0 +1,19 @@ +CFLAGS ?= -O0 -ggdb3 + +%.o: %.c + gcc -m32 $(CFLAGS) -c $< -o $@ -I ../ltc/headers + +LTC_OBJS := ../ltc/linux_x86/libtomcrypt_debug.a \ + ../ltc/linux_x86/libtommath.a + +.PHONY: progs +progs: verify resign + +verify: verify.o $(LTC_OBJS) + gcc -m32 $^ -o $@ + +resign: resign.o $(LTC_OBJS) + gcc -m32 $^ -o $@ + +clean: + rm -f verify resign verify.o resign.o diff --git a/src/plugins/pro1_data_zip/tools/resign.c b/src/plugins/pro1_data_zip/tools/resign.c new file mode 100644 index 0000000..4b864ce --- /dev/null +++ b/src/plugins/pro1_data_zip/tools/resign.c @@ -0,0 +1,193 @@ +#include +#include +#define LTM_DESC +#include "tomcrypt.h" + +// our replacement pub/privkeys +const unsigned char our_pubkey[140] = { + 0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00, 0xbb, 0xed, 0xa6, 0x26, 0xec, 0xe7, 0xc3, 0x60, 0x07, + 0xe7, 0xab, 0xf4, 0x05, 0x2f, 0xde, 0x6b, 0x86, 0x92, 0x65, 0x57, 0xf8, 0x57, 0xf5, 0xb2, 0x8f, + 0xe1, 0x2b, 0x4f, 0x73, 0xb1, 0x4a, 0xf1, 0xf2, 0xcc, 0x7f, 0x49, 0xd1, 0xd2, 0x48, 0xf1, 0x29, + 0x73, 0x59, 0x5c, 0x5d, 0x4a, 0x4f, 0x0f, 0x29, 0x15, 0xa8, 0xea, 0x7c, 0x92, 0x59, 0xa9, 0x8a, + 0x64, 0x5f, 0xba, 0x5a, 0x40, 0x43, 0x1f, 0x2d, 0x63, 0x5a, 0xd9, 0x31, 0x60, 0xd5, 0xa2, 0xac, + 0x99, 0xa1, 0xc9, 0x40, 0xf8, 0x92, 0xe5, 0x12, 0xe7, 0xa4, 0xeb, 0xe6, 0x02, 0xb3, 0xef, 0x5c, + 0xa4, 0x7f, 0x8f, 0x7f, 0xc8, 0x6f, 0xbe, 0x48, 0xaf, 0x0b, 0x67, 0x87, 0xd6, 0x73, 0xd3, 0xe8, + 0xba, 0x1f, 0x01, 0xfe, 0x9f, 0x35, 0xfd, 0xc1, 0x38, 0x7d, 0x39, 0x10, 0xed, 0x07, 0x77, 0x02, + 0xca, 0xf3, 0x52, 0xec, 0x7b, 0x1c, 0x83, 0x02, 0x03, 0x01, 0x00, 0x01 +}; + +const unsigned char our_privkey[608] = { + 0x30, 0x82, 0x02, 0x5c, 0x02, 0x01, 0x00, 0x02, 0x81, 0x81, 0x00, 0xbb, 0xed, 0xa6, 0x26, 0xec, + 0xe7, 0xc3, 0x60, 0x07, 0xe7, 0xab, 0xf4, 0x05, 0x2f, 0xde, 0x6b, 0x86, 0x92, 0x65, 0x57, 0xf8, + 0x57, 0xf5, 0xb2, 0x8f, 0xe1, 0x2b, 0x4f, 0x73, 0xb1, 0x4a, 0xf1, 0xf2, 0xcc, 0x7f, 0x49, 0xd1, + 0xd2, 0x48, 0xf1, 0x29, 0x73, 0x59, 0x5c, 0x5d, 0x4a, 0x4f, 0x0f, 0x29, 0x15, 0xa8, 0xea, 0x7c, + 0x92, 0x59, 0xa9, 0x8a, 0x64, 0x5f, 0xba, 0x5a, 0x40, 0x43, 0x1f, 0x2d, 0x63, 0x5a, 0xd9, 0x31, + 0x60, 0xd5, 0xa2, 0xac, 0x99, 0xa1, 0xc9, 0x40, 0xf8, 0x92, 0xe5, 0x12, 0xe7, 0xa4, 0xeb, 0xe6, + 0x02, 0xb3, 0xef, 0x5c, 0xa4, 0x7f, 0x8f, 0x7f, 0xc8, 0x6f, 0xbe, 0x48, 0xaf, 0x0b, 0x67, 0x87, + 0xd6, 0x73, 0xd3, 0xe8, 0xba, 0x1f, 0x01, 0xfe, 0x9f, 0x35, 0xfd, 0xc1, 0x38, 0x7d, 0x39, 0x10, + 0xed, 0x07, 0x77, 0x02, 0xca, 0xf3, 0x52, 0xec, 0x7b, 0x1c, 0x83, 0x02, 0x03, 0x01, 0x00, 0x01, + 0x02, 0x81, 0x80, 0x35, 0x7a, 0x4b, 0xa9, 0x51, 0x0a, 0x24, 0xd1, 0x5b, 0x7e, 0x84, 0x32, 0xb5, + 0x15, 0x29, 0xa4, 0x8c, 0x8f, 0x75, 0x52, 0x62, 0xc3, 0xd9, 0x11, 0x9e, 0x9a, 0xf3, 0x61, 0xb1, + 0x28, 0xf7, 0x0c, 0x41, 0xcd, 0x0a, 0xbd, 0xdd, 0x7d, 0x0b, 0x2f, 0xc1, 0x5d, 0x67, 0x44, 0xfe, + 0xf1, 0x29, 0xed, 0x45, 0x02, 0x3a, 0x66, 0xbb, 0xdb, 0x43, 0xb3, 0x98, 0xc3, 0xb6, 0x70, 0x07, + 0xc5, 0xb8, 0xb3, 0x95, 0x20, 0x6c, 0x7c, 0xad, 0x75, 0x02, 0x00, 0xa9, 0x1a, 0xea, 0xc6, 0xe0, + 0xc0, 0x7f, 0x0e, 0xc1, 0x12, 0x05, 0xe7, 0xf1, 0x32, 0x0d, 0x5a, 0x1a, 0xa3, 0xa5, 0xec, 0xe5, + 0x80, 0x0c, 0x04, 0x3e, 0x7f, 0xfb, 0x0b, 0x49, 0xbe, 0x67, 0xef, 0x8a, 0x5e, 0x98, 0x7e, 0xa1, + 0xb4, 0x4f, 0x57, 0x3d, 0x1b, 0xe3, 0xe9, 0x33, 0x3f, 0x91, 0x0c, 0x14, 0x83, 0xbc, 0xf1, 0x8c, + 0x47, 0xbc, 0xa1, 0x02, 0x41, 0x00, 0xfa, 0x53, 0xe3, 0x8e, 0x78, 0x1d, 0xae, 0x89, 0x03, 0x9c, + 0x0e, 0x9b, 0xd4, 0x70, 0xa4, 0x8c, 0x01, 0x9c, 0x90, 0x66, 0x1c, 0xa7, 0xf4, 0x86, 0x3f, 0x57, + 0x1f, 0xc5, 0xc3, 0x83, 0xe9, 0x82, 0x62, 0xbd, 0x7f, 0xdf, 0xd4, 0xbf, 0x56, 0x1f, 0xfe, 0xa4, + 0x5a, 0x88, 0x68, 0x47, 0xbe, 0xd5, 0xe1, 0x21, 0xb3, 0xf7, 0xfb, 0x7f, 0xac, 0xe6, 0x9d, 0x7f, + 0x9b, 0x6d, 0xb9, 0x16, 0x2b, 0xe3, 0x02, 0x41, 0x00, 0xc0, 0x2f, 0xca, 0x92, 0x58, 0x37, 0xa6, + 0x6f, 0x83, 0x7b, 0x0d, 0xe0, 0xd3, 0xd0, 0x60, 0x9e, 0xfa, 0x19, 0x0d, 0x82, 0x35, 0x93, 0xd8, + 0x18, 0xa7, 0x80, 0x55, 0x9d, 0xa3, 0x84, 0xd2, 0x2a, 0xd0, 0x9a, 0x1a, 0xa1, 0x21, 0xaf, 0x72, + 0xac, 0x4f, 0xf6, 0xdb, 0x39, 0x64, 0x01, 0x81, 0xc5, 0xda, 0x28, 0x3f, 0x1a, 0xf9, 0xc1, 0xc5, + 0x2c, 0x0d, 0x16, 0x72, 0x80, 0x41, 0xc1, 0x6e, 0xe1, 0x02, 0x40, 0x49, 0x29, 0x4f, 0x6e, 0x8a, + 0x28, 0x92, 0xa4, 0x34, 0xcb, 0xdd, 0x71, 0x29, 0xcb, 0xaa, 0x2b, 0xc9, 0x24, 0xcb, 0x07, 0x2d, + 0x04, 0xe1, 0x70, 0x82, 0xfe, 0xa1, 0xa8, 0x99, 0x15, 0xea, 0x9f, 0x52, 0xe0, 0x73, 0x89, 0x25, + 0x92, 0xae, 0x47, 0x37, 0x93, 0x2d, 0x6a, 0x84, 0x9f, 0xc3, 0x64, 0x9b, 0x21, 0xd0, 0x89, 0x7f, + 0x95, 0xb7, 0x20, 0xc7, 0x93, 0x4e, 0x07, 0xe9, 0x7a, 0x53, 0x65, 0x02, 0x40, 0x6c, 0x89, 0x91, + 0x09, 0xdd, 0x30, 0x70, 0x9a, 0x81, 0xd2, 0xb9, 0x1f, 0xc3, 0xff, 0xe6, 0xd1, 0x61, 0xc5, 0x4c, + 0x4f, 0xc1, 0x1a, 0x61, 0xec, 0x6a, 0x8c, 0x9b, 0xcd, 0x8f, 0x4f, 0xaf, 0xb1, 0xe6, 0x65, 0x61, + 0xac, 0xa6, 0x6d, 0x83, 0x81, 0xb5, 0x17, 0x60, 0xef, 0xa4, 0x7f, 0x05, 0x5f, 0x4b, 0xb9, 0x77, + 0x0a, 0x31, 0x0b, 0x31, 0xe3, 0x92, 0xf0, 0x9e, 0x71, 0xb8, 0xb1, 0x19, 0x81, 0x02, 0x41, 0x00, + 0xad, 0x4f, 0x5f, 0x26, 0x06, 0x26, 0x3f, 0xdb, 0x17, 0x2d, 0xd4, 0x0a, 0xcd, 0xa0, 0x76, 0x9a, + 0xef, 0x84, 0x1b, 0x59, 0xf8, 0x7d, 0x3f, 0x6f, 0x5d, 0xbf, 0x76, 0x42, 0xff, 0xe8, 0x71, 0x45, + 0xcb, 0x6e, 0xb7, 0xbe, 0x87, 0x72, 0xd4, 0x2a, 0xbb, 0x9e, 0xd2, 0xc6, 0x61, 0xc4, 0xce, 0xfb, + 0xb4, 0xa9, 0x3c, 0x75, 0xac, 0xa3, 0x89, 0xdf, 0x34, 0x98, 0xa9, 0x29, 0x6b, 0x79, 0xca, 0xcb +}; + +void usage(const char *prog) { + fprintf(stderr, "Usage: %s \n", prog); + fprintf(stderr, "\nReplaces the signature on an encrypted zip file \n" + "with one signed by our own private key.\n"); +} + +int main(int argc, const char **argv) { + rsa_key ourkey; + int err; + int verified = 0, attach_new_sig = 0; + unsigned char hash1[20], hash2[20], srsly[6]; + size_t amt, total = 0; + int sha1_idx, sprng_idx; + hash_state md, md2; + + ltc_mp = ltm_desc; + + if ((sha1_idx = register_hash(&sha1_desc)) == -1) { + fprintf(stderr, "Could not register SHA1 hash descriptor\n"); + return -1; + } + if ((sprng_idx = register_prng(&sprng_desc)) == -1) { + fprintf(stderr, "Could not register sprng PRNG\n"); + return -1; + } + + sha1_init(&md); + sha1_init(&md2); + + if (argc < 2) { + usage(argv[0]); + return 2; + } + if ((err = rsa_import(our_privkey, sizeof(our_privkey), &ourkey)) != CRYPT_OK) { + fprintf(stderr, "rsa_import: %s\n", error_to_string(err)); + return 1; + } + + FILE *zip_fd = fopen(argv[1], "r+b"); + if (zip_fd == NULL) { + perror("fopen(zip_fd)"); + return 1; + } + fseek(zip_fd, 0, SEEK_END); + amt = ftell(zip_fd); + + fseek(zip_fd, -5, SEEK_END); + if (fread(srsly, 1, 5, zip_fd) != 5) { + perror("fread(srsly)"); + return 1; + } + if (strncmp(srsly, "SRSLY", 5) != 0) { + printf("creating new sig for %s...\n", argv[1]); + attach_new_sig = 1; + } else { + amt -= 133; + } + + unsigned char buf[0x10000], sig[256]; + size_t got = 0, readsize = 0; + off_t pos = 0; + long curpos = 0; + + while (pos < amt) { + fseek(zip_fd, pos, SEEK_SET); + curpos = ftell(zip_fd); + readsize = (amt < 0x10000) ? amt : 0x10000; + got = fread(buf, 1, readsize, zip_fd); + if (got != readsize) { + perror("fread(zip_fd)"); + fclose(zip_fd); + return 1; + } + sha1_process(&md, buf, got); + printf("processed %d bytes at %lu\n", got, curpos); + total += got; + if (pos + got >= amt) { + break; + } + pos += 0x1000000; + if (pos + 0x10000 > amt) { + pos = amt - 0x10000; + } + } + + printf("Read %lu bytes total..\n", total); + + sha1_done(&md, hash1); + sha1_process(&md2, hash1, 20); + sha1_done(&md2, hash2); + + printf("hash1: "); + for (int i = 0; i < 20; i++) { + printf("%02x", hash1[i]); + } + printf("\n"); + printf("hash2: "); + for (int i = 0; i < 20; i++) { + printf("%02x", hash2[i]); + } + printf("\n"); + + unsigned long siglen = 256; + if ((err = rsa_sign_hash_ex(hash2, sizeof(hash2), sig, &siglen, LTC_PKCS_1_V1_5, NULL, sprng_idx, sha1_idx, 0, &ourkey)) != CRYPT_OK) { + fprintf(stderr, "rsa_sign_hash_ex: (%d) %s\n", err, error_to_string(err)); + return 1; + } + assert(siglen == 128); + + if (attach_new_sig) { + zip_fd = fopen(argv[1], "ab"); + if (fwrite(sig, 1, siglen, zip_fd) != siglen) { + perror("fwrite(sig)"); + fclose(zip_fd); + return 1; + } + if (fwrite("SRSLY", 1, 5, zip_fd) != 5) { + perror("fwrite(SRSLY)"); + fclose(zip_fd); + return 1; + } + } else { + zip_fd = fopen(argv[1], "r+b"); + fseek(zip_fd, -133, SEEK_END); + if (fwrite(sig, 1, siglen, zip_fd) != siglen) { + perror("fwrite(sig)"); + fclose(zip_fd); + return 1; + } + } + fclose(zip_fd); + + return 0; +} diff --git a/src/plugins/pro1_data_zip/tools/verify.c b/src/plugins/pro1_data_zip/tools/verify.c new file mode 100644 index 0000000..3785324 --- /dev/null +++ b/src/plugins/pro1_data_zip/tools/verify.c @@ -0,0 +1,762 @@ +#include +#include +#include +#include +#define LTM_DESC +#include "tomcrypt.h" + +uint8_t official_sig_data[8576] = { + 0x97, 0x38, 0xf8, 0xd5, 0xed, 0xe5, 0x97, 0xd8, 0xf4, 0x7d, 0x31, 0x67, 0x36, 0xfa, 0x9f, 0x7b, + 0x43, 0x36, 0xc0, 0xbf, 0x90, 0x32, 0x95, 0x49, 0x1f, 0xf1, 0x41, 0xb5, 0x9c, 0x88, 0xe2, 0xaf, + 0x41, 0x2a, 0xce, 0xc1, 0x8b, 0x6a, 0x06, 0x6b, 0x92, 0x10, 0x47, 0xde, 0x2c, 0xdb, 0x57, 0xae, + 0x0d, 0x32, 0xbb, 0x39, 0xd4, 0x1d, 0x3d, 0xb1, 0xc3, 0xd3, 0xef, 0x5a, 0x16, 0x18, 0x57, 0xea, + 0x45, 0x98, 0x11, 0xb5, 0x4b, 0xdb, 0x4c, 0x55, 0xb0, 0x61, 0xde, 0x15, 0x89, 0xbb, 0x74, 0x31, + 0xbe, 0x7b, 0x44, 0xdb, 0xe5, 0xd3, 0x7c, 0x48, 0xa4, 0x30, 0xa2, 0x23, 0x47, 0x49, 0x8f, 0xef, + 0x9a, 0xbc, 0x65, 0xda, 0xc8, 0xaa, 0x7f, 0x38, 0x53, 0x48, 0xf6, 0xe8, 0xba, 0x93, 0x92, 0x21, + 0xb9, 0xce, 0xdf, 0x55, 0xdf, 0xc4, 0x3a, 0x35, 0xec, 0xff, 0x9b, 0xdf, 0xf7, 0xe6, 0xd7, 0x6f, + 0x7c, 0x82, 0xeb, 0x93, 0x37, 0x40, 0x64, 0xb1, 0x3c, 0x98, 0x3c, 0xfa, 0x20, 0x5e, 0xbf, 0x57, + 0x46, 0xc3, 0x78, 0x17, 0x75, 0xdf, 0x0b, 0x5f, 0x33, 0xfb, 0x9c, 0xd2, 0x47, 0x53, 0xff, 0xde, + 0x24, 0xe1, 0x25, 0x06, 0x15, 0x7b, 0x94, 0xad, 0xe8, 0x38, 0x62, 0x83, 0xd8, 0x1a, 0xa1, 0xde, + 0xd9, 0x02, 0x08, 0xc8, 0x41, 0x1d, 0x07, 0xea, 0x99, 0x8c, 0x10, 0xf2, 0xf9, 0x1b, 0x60, 0x18, + 0x97, 0x8a, 0x84, 0xa5, 0x7f, 0xb8, 0x20, 0x36, 0xbe, 0x33, 0x0b, 0x8d, 0xba, 0x97, 0xdf, 0xfe, + 0x01, 0xb0, 0x1e, 0x0a, 0xee, 0x90, 0x05, 0xb6, 0x6f, 0x15, 0xbc, 0x22, 0xc0, 0x34, 0xfe, 0xeb, + 0xda, 0x84, 0x2c, 0xb6, 0xb8, 0xa0, 0xc7, 0x44, 0x2e, 0x82, 0x1c, 0x1b, 0xb2, 0xe4, 0x2d, 0x24, + 0xc0, 0x4b, 0x6e, 0x53, 0x16, 0xa4, 0x6e, 0xd0, 0x27, 0x74, 0x87, 0x4b, 0x08, 0xb4, 0x85, 0xbe, + 0xa0, 0xcc, 0xf5, 0x58, 0x96, 0x31, 0x70, 0x22, 0x24, 0xe6, 0xcc, 0xde, 0xc6, 0x1c, 0xd1, 0x91, + 0xde, 0xbd, 0x65, 0x04, 0x51, 0xd2, 0xfa, 0x2f, 0x2e, 0xdb, 0x90, 0xc8, 0x36, 0x4b, 0xc3, 0x23, + 0x1b, 0x3e, 0xe6, 0x21, 0x8f, 0x35, 0xa7, 0x61, 0xf6, 0xb0, 0x74, 0xf3, 0xfe, 0x27, 0x32, 0x9f, + 0xed, 0x18, 0xb8, 0x2e, 0x00, 0x56, 0x26, 0xdc, 0x60, 0xe5, 0xb7, 0xa6, 0x12, 0x6e, 0x14, 0x58, + 0x31, 0xc3, 0x45, 0xff, 0x75, 0x86, 0x8d, 0x85, 0x50, 0x97, 0x66, 0x6b, 0x04, 0x59, 0x7b, 0xbf, + 0xaa, 0x84, 0x77, 0xb3, 0xdd, 0x90, 0xbb, 0x86, 0xc5, 0x36, 0x8f, 0xb0, 0x7e, 0xe3, 0xaf, 0x49, + 0x47, 0x47, 0x6b, 0x4e, 0xe3, 0x18, 0x45, 0x09, 0x83, 0x0c, 0xc1, 0x5d, 0x96, 0x80, 0x5a, 0xd7, + 0xc9, 0x0a, 0x1b, 0xc8, 0x85, 0xac, 0xf2, 0x61, 0x65, 0x38, 0xdb, 0xef, 0x73, 0x02, 0x40, 0x2e, + 0x74, 0x7c, 0x8d, 0x4a, 0x5c, 0x07, 0x4a, 0xf1, 0xb1, 0x41, 0x10, 0x29, 0xa8, 0x2f, 0x0e, 0xe9, + 0x52, 0x3c, 0x6a, 0xa9, 0x9b, 0x86, 0x9b, 0x5d, 0x66, 0x30, 0x2e, 0x74, 0x25, 0xdb, 0xfb, 0x50, + 0x4b, 0x8e, 0x4e, 0xca, 0x0a, 0x8e, 0xfe, 0x99, 0xfe, 0x86, 0xf6, 0x75, 0x30, 0x60, 0x68, 0x90, + 0xb3, 0x63, 0xbe, 0xb7, 0xd1, 0xe4, 0x4c, 0xe5, 0xc2, 0x1e, 0xb0, 0x10, 0x48, 0x03, 0xeb, 0x1d, + 0xc4, 0xdf, 0x3a, 0x66, 0x8e, 0x3a, 0x18, 0x5f, 0xa9, 0x2c, 0x5f, 0xf8, 0xa3, 0x7b, 0x82, 0x5b, + 0x77, 0x91, 0x28, 0x23, 0x48, 0x11, 0x3d, 0xd8, 0x96, 0x9d, 0xf8, 0x12, 0x5a, 0x6e, 0x50, 0x3c, + 0x20, 0x24, 0x21, 0x88, 0x77, 0x21, 0xf5, 0x27, 0x06, 0xf8, 0xe1, 0x03, 0x38, 0x7e, 0x08, 0x0f, + 0xd5, 0xbf, 0x29, 0x38, 0x10, 0xb3, 0x0a, 0x76, 0x1d, 0x2c, 0xc8, 0x9e, 0xbb, 0x9f, 0x04, 0x7d, + 0x69, 0x57, 0x71, 0x62, 0xfa, 0x91, 0xa3, 0xd1, 0xb0, 0xee, 0x65, 0x81, 0xb7, 0x76, 0xb2, 0x35, + 0x14, 0x43, 0xed, 0x39, 0xe1, 0xb5, 0xab, 0xfc, 0xad, 0xa4, 0x6a, 0x34, 0x23, 0x5e, 0x0f, 0xb2, + 0x42, 0xa7, 0x19, 0x8c, 0x6b, 0x50, 0x67, 0x5d, 0x75, 0xff, 0xa1, 0xb9, 0xb9, 0x4c, 0xb1, 0x83, + 0xa8, 0x8e, 0xb9, 0x8a, 0x0b, 0xd3, 0x24, 0xb6, 0x60, 0xec, 0x50, 0xed, 0x84, 0x16, 0x7d, 0x73, + 0xac, 0x69, 0x2c, 0x43, 0x19, 0xd2, 0x8b, 0xe1, 0xd5, 0x66, 0x4f, 0x06, 0xcd, 0xd9, 0x10, 0xbc, + 0x95, 0xde, 0x5d, 0x47, 0x4d, 0x4a, 0x58, 0xa7, 0x42, 0x71, 0x1a, 0x52, 0x10, 0x20, 0x35, 0x51, + 0xf3, 0x23, 0x1c, 0x50, 0x9f, 0x2f, 0x06, 0x88, 0xf1, 0x5b, 0xec, 0x11, 0xd3, 0xdb, 0x89, 0xa6, + 0x4f, 0x53, 0xda, 0xe7, 0xbb, 0xd6, 0x04, 0xb9, 0x63, 0x96, 0x9c, 0x12, 0x18, 0xba, 0x3f, 0x64, + 0x23, 0x57, 0x1f, 0x97, 0x38, 0xc0, 0x39, 0x38, 0x19, 0x10, 0x2b, 0xbb, 0x8f, 0x7f, 0x9d, 0xc6, + 0x85, 0x7c, 0x6c, 0x06, 0xbd, 0xc0, 0x4e, 0x8f, 0xd3, 0x22, 0x81, 0xaf, 0x3d, 0x79, 0x21, 0x73, + 0x08, 0x71, 0x95, 0xdf, 0x0e, 0xe8, 0x0f, 0xc6, 0x87, 0xab, 0x23, 0x04, 0x9a, 0x20, 0x72, 0x54, + 0x9e, 0x3e, 0x5d, 0x87, 0x6b, 0xf4, 0xb1, 0xf6, 0x64, 0x0b, 0x2e, 0x01, 0x9a, 0x65, 0xa1, 0x22, + 0x6a, 0xa3, 0x66, 0x3d, 0x93, 0xb3, 0x93, 0x2c, 0x86, 0xe6, 0x8d, 0x4f, 0xf3, 0x57, 0xec, 0xb4, + 0xdb, 0x8e, 0x4c, 0xf3, 0x17, 0x44, 0x88, 0xbd, 0xb9, 0xcc, 0xbf, 0xf8, 0xae, 0xe8, 0xa4, 0xa5, + 0x2e, 0xa9, 0x75, 0xc1, 0xbe, 0x49, 0x60, 0xbf, 0x2f, 0x99, 0x2a, 0x6e, 0x0c, 0x07, 0x1e, 0x62, + 0xdb, 0x7f, 0x81, 0xad, 0x5a, 0x8f, 0x7c, 0xe3, 0x67, 0x5c, 0x20, 0x03, 0xeb, 0x67, 0x69, 0x8d, + 0x46, 0x12, 0x31, 0x17, 0x48, 0x85, 0xf8, 0xf2, 0x11, 0xaa, 0xc4, 0x72, 0xc0, 0xbb, 0xa2, 0xd9, + 0x52, 0x88, 0x5c, 0x36, 0xac, 0x97, 0x40, 0x52, 0xe9, 0xf9, 0x23, 0xce, 0x8c, 0xbb, 0x54, 0xca, + 0x13, 0x0b, 0xe0, 0x9c, 0xcd, 0xde, 0x44, 0xca, 0xfc, 0xae, 0x6f, 0x8f, 0xc5, 0x4d, 0xa8, 0x9e, + 0xa0, 0x48, 0xe7, 0xd1, 0xe2, 0x07, 0x6f, 0x8a, 0x82, 0xaf, 0xa1, 0xc8, 0x43, 0xa2, 0xc6, 0xc5, + 0x4f, 0xef, 0x5d, 0x51, 0x13, 0xfb, 0xeb, 0xb8, 0xaf, 0xef, 0xb4, 0x10, 0x15, 0x8e, 0x42, 0x90, + 0xb7, 0x5a, 0x2e, 0xef, 0x23, 0x1f, 0x45, 0x56, 0xd9, 0xcb, 0xf0, 0x37, 0xf1, 0xbf, 0x6d, 0x4d, + 0x2a, 0xb4, 0x55, 0x6d, 0x9f, 0x42, 0x5e, 0x26, 0xc2, 0x44, 0x99, 0x0e, 0x44, 0xf4, 0xb4, 0xf8, + 0x36, 0x16, 0x7e, 0x17, 0xfa, 0xac, 0x9d, 0xa2, 0x76, 0x5c, 0xd4, 0x86, 0x07, 0xbe, 0xb5, 0x6b, + 0xb5, 0x42, 0x66, 0xc6, 0x57, 0xc4, 0xfc, 0x5b, 0xb2, 0x8e, 0x57, 0x04, 0x3a, 0xe1, 0x2f, 0x51, + 0x27, 0xee, 0x18, 0x2c, 0x68, 0x7f, 0x15, 0x2f, 0x51, 0x2c, 0xb4, 0xcd, 0x26, 0xa4, 0x9d, 0xa1, + 0xd2, 0x72, 0x36, 0xbf, 0x6b, 0x05, 0xcf, 0xb0, 0x58, 0x07, 0x1f, 0x83, 0x0e, 0x48, 0x8e, 0x9c, + 0x32, 0x12, 0x04, 0xa3, 0xa3, 0xe7, 0x8d, 0xa3, 0x23, 0xe6, 0x79, 0x06, 0x30, 0x6a, 0x15, 0x5c, + 0xfe, 0xb5, 0x8a, 0xba, 0x78, 0x78, 0xb1, 0x5f, 0x9c, 0x5c, 0xca, 0x39, 0x39, 0x5f, 0x01, 0x13, + 0xe1, 0x50, 0xed, 0x90, 0xfc, 0xdc, 0x99, 0x6c, 0x1a, 0xb9, 0xbb, 0x23, 0x7a, 0x56, 0x71, 0xb3, + 0x0f, 0xf3, 0x41, 0x14, 0xfb, 0x8e, 0x88, 0x34, 0x43, 0x0c, 0x72, 0x97, 0xfb, 0x8e, 0x42, 0x24, + 0x7a, 0xea, 0xac, 0xb6, 0xee, 0xa1, 0x7d, 0xbf, 0xc9, 0xdf, 0xbe, 0xeb, 0xce, 0x50, 0xf7, 0x0e, + 0x76, 0xe1, 0x11, 0x06, 0x4e, 0x24, 0x95, 0x63, 0xe6, 0x94, 0x3f, 0x29, 0x42, 0xd2, 0x6a, 0x22, + 0xc5, 0x26, 0xf4, 0xfb, 0x76, 0x93, 0xf3, 0xf7, 0x6d, 0xb8, 0x3e, 0x70, 0x1c, 0x5c, 0xf1, 0xc2, + 0x07, 0x4d, 0xfe, 0x78, 0x7a, 0x46, 0xd4, 0x69, 0x55, 0x1a, 0x53, 0xa6, 0xee, 0xcd, 0xd7, 0xee, + 0xc1, 0x79, 0x40, 0xf3, 0x4a, 0x48, 0x4f, 0x0b, 0x65, 0x0e, 0x2d, 0x23, 0x3d, 0x96, 0xbe, 0xca, + 0x1a, 0x98, 0xf5, 0x6e, 0x64, 0x7c, 0xac, 0x1b, 0xf2, 0x2e, 0x44, 0xf3, 0x50, 0xc8, 0x86, 0xe6, + 0x31, 0xee, 0x21, 0x40, 0x48, 0xc7, 0xf8, 0x3d, 0xbd, 0x16, 0xc4, 0x54, 0xe1, 0x9e, 0x12, 0x9f, + 0xf3, 0x45, 0xc0, 0x35, 0x30, 0xf3, 0x1c, 0x3f, 0xdc, 0x1d, 0xf8, 0x9f, 0x06, 0x3f, 0x01, 0x8b, + 0xed, 0xa8, 0xf9, 0xca, 0x4b, 0x42, 0xe4, 0x8f, 0x53, 0xb2, 0xb4, 0xbf, 0xa9, 0x55, 0xf8, 0x3f, + 0x2f, 0x7c, 0x25, 0x78, 0x3a, 0xfd, 0x25, 0xbd, 0xd7, 0x2f, 0xd7, 0x29, 0x47, 0x64, 0xa6, 0x7f, + 0x4f, 0x5f, 0x0f, 0xb6, 0x75, 0xb6, 0xbc, 0x33, 0xd4, 0xe4, 0x0a, 0x5e, 0x91, 0xc6, 0x9f, 0x92, + 0xb6, 0x9e, 0x8c, 0x33, 0x50, 0x88, 0xc8, 0x28, 0xcd, 0x8f, 0x50, 0x9b, 0x7c, 0x96, 0x4e, 0x6c, + 0x9d, 0x57, 0x26, 0x3f, 0x3a, 0x95, 0xc2, 0x7a, 0x60, 0xd7, 0xc9, 0x7c, 0xcd, 0xaa, 0xf3, 0xd6, + 0xb0, 0xb5, 0x6e, 0xa2, 0x92, 0xbf, 0x96, 0x16, 0x45, 0xf6, 0xe2, 0x13, 0x18, 0x7c, 0x61, 0xd9, + 0x48, 0xa1, 0x7f, 0x6c, 0xf5, 0x38, 0xb5, 0xf1, 0x73, 0xf8, 0xcd, 0xca, 0x5e, 0x18, 0xba, 0x31, + 0xca, 0x8e, 0xc0, 0xad, 0x91, 0x20, 0xf6, 0xef, 0xf5, 0x6f, 0xac, 0xdf, 0x8c, 0x15, 0x25, 0xbe, + 0x3c, 0xbb, 0xf4, 0x3f, 0x92, 0xfd, 0x9a, 0x04, 0xb0, 0xe2, 0x27, 0x5c, 0x73, 0x1b, 0xd7, 0xc5, + 0xa2, 0x03, 0x6f, 0x83, 0x7d, 0xc6, 0x44, 0x85, 0x62, 0x40, 0xe4, 0x0f, 0x19, 0xac, 0x64, 0x69, + 0x1f, 0x24, 0x03, 0x42, 0x69, 0x36, 0xbf, 0x58, 0x69, 0xf7, 0xec, 0x5d, 0x31, 0xb9, 0x5a, 0x7d, + 0x71, 0x4f, 0x9c, 0x67, 0x89, 0xc4, 0x2e, 0xc4, 0x42, 0x19, 0x20, 0xc0, 0x5a, 0x09, 0x86, 0xce, + 0x93, 0x4f, 0xfc, 0xbe, 0xaa, 0x79, 0xa3, 0x36, 0xdd, 0xf0, 0xad, 0xa7, 0x2a, 0x52, 0x5a, 0xb5, + 0x90, 0x6a, 0x57, 0x90, 0x55, 0x89, 0xfd, 0xb9, 0x1c, 0x88, 0x3e, 0x73, 0x6b, 0x22, 0xa7, 0xcb, + 0xb3, 0xa9, 0x55, 0x82, 0xa4, 0x9d, 0xa9, 0x4f, 0x99, 0x0a, 0x2c, 0x60, 0xdc, 0x27, 0xf8, 0x4c, + 0x99, 0xaa, 0x78, 0x63, 0x70, 0xbc, 0x80, 0xae, 0x42, 0x28, 0xce, 0xea, 0x4d, 0x11, 0x50, 0x26, + 0xaf, 0xf8, 0x48, 0x76, 0xc8, 0xc0, 0xe2, 0xf9, 0x9d, 0xd7, 0xb9, 0x7b, 0x2d, 0x38, 0xd3, 0xe4, + 0x38, 0x8a, 0x00, 0xb8, 0x9b, 0x1d, 0xd2, 0x92, 0xb9, 0x94, 0xa8, 0x6a, 0xb0, 0x5d, 0xb8, 0x50, + 0x65, 0x35, 0xf0, 0xd8, 0xf7, 0xb0, 0x64, 0xc1, 0x4b, 0xa1, 0xb9, 0xc7, 0x60, 0xf6, 0x2e, 0x20, + 0x7f, 0xc9, 0x61, 0x64, 0x8f, 0x2f, 0x68, 0x94, 0x8d, 0x12, 0x0f, 0x29, 0x1c, 0x06, 0xe3, 0x23, + 0x73, 0x49, 0x6c, 0x0c, 0xb1, 0x25, 0x02, 0x79, 0xea, 0x36, 0xcf, 0x2d, 0xc8, 0x54, 0xa5, 0x88, + 0xa6, 0x89, 0x45, 0x35, 0xb6, 0x71, 0x3c, 0x20, 0xee, 0x34, 0x1a, 0x32, 0x37, 0x58, 0x6e, 0x92, + 0xc5, 0xfe, 0x8a, 0x03, 0x72, 0x1d, 0xe2, 0x2e, 0x41, 0x1c, 0xd2, 0x7b, 0x4a, 0xef, 0x3e, 0x53, + 0x4b, 0x5d, 0x36, 0xa3, 0x5a, 0x4b, 0xee, 0x4d, 0xd1, 0x5d, 0x7f, 0x4f, 0x58, 0x3a, 0xf8, 0x76, + 0x46, 0x74, 0x29, 0x85, 0xb1, 0x46, 0x85, 0xa3, 0x8d, 0x7a, 0x34, 0x96, 0x2e, 0xed, 0x67, 0x7d, + 0x48, 0x87, 0x38, 0xe9, 0xdb, 0x9d, 0x26, 0x0b, 0x40, 0xe5, 0xb7, 0xde, 0x64, 0x1d, 0x85, 0x7b, + 0x42, 0xf4, 0xdc, 0x6d, 0xe5, 0x64, 0x8b, 0xb5, 0xea, 0x33, 0x75, 0x40, 0x06, 0xca, 0x88, 0x52, + 0x94, 0x07, 0xd1, 0xbe, 0xa3, 0x1d, 0x08, 0x5e, 0x3b, 0xf8, 0x9e, 0xb9, 0x79, 0x94, 0xb1, 0xbb, + 0x01, 0xb3, 0x71, 0x18, 0x0c, 0x2a, 0x66, 0x67, 0x7c, 0xcf, 0x0e, 0x3d, 0x1c, 0xfd, 0xb6, 0x19, + 0xeb, 0xa6, 0xde, 0xc4, 0xda, 0x43, 0x29, 0xe9, 0xb0, 0xb7, 0x82, 0xbf, 0x3a, 0x87, 0xf1, 0x9e, + 0xff, 0x6d, 0x7b, 0xee, 0xe0, 0x93, 0x30, 0x5c, 0xbf, 0xdf, 0xbd, 0x92, 0x71, 0x29, 0xff, 0x01, + 0x27, 0x4a, 0x7e, 0xff, 0x33, 0xfb, 0xf1, 0x24, 0x84, 0xd0, 0xb5, 0x34, 0xf3, 0x51, 0x5b, 0x0d, + 0x32, 0x69, 0x53, 0x16, 0x73, 0x8e, 0x3b, 0x6f, 0x70, 0x47, 0x80, 0xdc, 0x94, 0xa2, 0x13, 0x4a, + 0x7d, 0x80, 0x30, 0x06, 0xe5, 0xb3, 0x81, 0x84, 0x62, 0xe7, 0x23, 0x70, 0x78, 0xed, 0xb8, 0xb7, + 0x8c, 0xc0, 0x36, 0x7e, 0x0b, 0x66, 0x98, 0x7b, 0x58, 0xc1, 0x74, 0x82, 0xc3, 0xec, 0xd6, 0x80, + 0xcc, 0x80, 0x87, 0x9a, 0x74, 0xf7, 0xe6, 0x45, 0xea, 0x7d, 0x11, 0xe2, 0x11, 0x6e, 0xf8, 0x8e, + 0xcf, 0x03, 0xbd, 0x65, 0xb0, 0x88, 0xc9, 0x66, 0x56, 0xf2, 0xd1, 0x4c, 0x38, 0x11, 0xb1, 0x2e, + 0xf5, 0x15, 0x5b, 0xa5, 0xca, 0x6b, 0x35, 0x4b, 0x63, 0xf4, 0xe1, 0x5f, 0xb6, 0xa8, 0xb2, 0xd2, + 0x5c, 0x4b, 0x74, 0xfc, 0x3e, 0x7c, 0x96, 0x5e, 0xe8, 0x94, 0x25, 0xc4, 0xfb, 0x79, 0x1a, 0x42, + 0x6b, 0xf2, 0x72, 0x4e, 0x0d, 0xb0, 0x5e, 0xb4, 0x5c, 0x3e, 0xe4, 0x72, 0x1a, 0x2b, 0x31, 0x97, + 0x21, 0xe6, 0x38, 0x61, 0x32, 0xea, 0xc3, 0x5f, 0x91, 0x95, 0xb8, 0xa2, 0x33, 0x7a, 0xa5, 0xc6, + 0x2d, 0xfe, 0x38, 0xbd, 0x5d, 0x1a, 0xe6, 0x0d, 0x2a, 0xc6, 0xf6, 0xd3, 0xf2, 0x00, 0x7c, 0xac, + 0xe2, 0x90, 0x8c, 0x11, 0xd3, 0x52, 0x0b, 0x46, 0xcf, 0xb3, 0x72, 0xf9, 0xfa, 0x96, 0xac, 0x0d, + 0x12, 0xaf, 0x4e, 0x55, 0x88, 0x3a, 0x37, 0x38, 0xbe, 0x75, 0x83, 0x6b, 0xc8, 0x8c, 0xe8, 0x28, + 0xe3, 0x4b, 0xca, 0xe2, 0x13, 0xac, 0x7c, 0x43, 0xfc, 0xf3, 0x2a, 0x89, 0xf0, 0x78, 0x2c, 0x76, + 0xd2, 0xd4, 0x74, 0x49, 0x12, 0x64, 0x6e, 0xe3, 0xc8, 0x71, 0x32, 0x20, 0x3c, 0x90, 0x47, 0xeb, + 0xec, 0xbb, 0x09, 0xea, 0x4e, 0x16, 0x27, 0x12, 0x99, 0x95, 0x62, 0xe6, 0x37, 0x18, 0x46, 0xce, + 0x84, 0x2c, 0x56, 0xbe, 0xd1, 0x36, 0x39, 0xff, 0xaa, 0x8d, 0x4a, 0xa6, 0xb4, 0x42, 0x83, 0x67, + 0xb0, 0xc6, 0xdc, 0xe2, 0x08, 0xf1, 0x54, 0x4a, 0x81, 0xf1, 0x07, 0x8a, 0x35, 0xf9, 0xcc, 0x8e, + 0x26, 0xfc, 0x7f, 0xdd, 0x95, 0x42, 0x97, 0x92, 0xdc, 0xf1, 0x80, 0x3a, 0x62, 0x72, 0xc8, 0x69, + 0x1d, 0x61, 0x7f, 0x44, 0xe7, 0x45, 0x71, 0x58, 0xd8, 0x8c, 0xb9, 0x2f, 0xec, 0xe4, 0xc0, 0x03, + 0xe6, 0xc0, 0x86, 0xa0, 0xe2, 0xc8, 0xf1, 0x24, 0x4e, 0xf3, 0xca, 0x2e, 0x49, 0x5a, 0x16, 0x60, + 0x4c, 0xe5, 0xd2, 0x88, 0xd6, 0x16, 0x3b, 0x93, 0x44, 0x14, 0xe9, 0x26, 0xf0, 0x1e, 0x0e, 0x9d, + 0xb1, 0x3f, 0xe7, 0xe3, 0xa3, 0x81, 0x3b, 0x07, 0xe7, 0xe1, 0xdf, 0xd6, 0xe9, 0x86, 0x6f, 0x66, + 0xdc, 0x20, 0xe9, 0x19, 0x07, 0x56, 0xbc, 0x76, 0x91, 0x20, 0x97, 0xc9, 0x7a, 0x70, 0xbd, 0x40, + 0x64, 0x2f, 0xbf, 0x09, 0x33, 0x70, 0x67, 0x49, 0x23, 0x9c, 0x30, 0x1c, 0x28, 0x74, 0x0a, 0xdb, + 0x52, 0x53, 0xf1, 0x31, 0xb8, 0x5e, 0xaa, 0xb0, 0xca, 0x25, 0xda, 0xb2, 0x59, 0x52, 0x75, 0x83, + 0x99, 0xfa, 0x52, 0xd2, 0xf2, 0xeb, 0xaf, 0xc5, 0x1b, 0x94, 0xd6, 0xa3, 0x1c, 0xa0, 0xba, 0x02, + 0xe6, 0x94, 0xa4, 0x85, 0x52, 0x51, 0xb9, 0xeb, 0x09, 0xa4, 0x9b, 0xc3, 0x81, 0xb6, 0xcc, 0x21, + 0x7e, 0x36, 0x78, 0x31, 0x95, 0xa0, 0x9f, 0x4a, 0x96, 0x87, 0x54, 0xef, 0x09, 0x8c, 0x5a, 0x63, + 0xfd, 0x39, 0xa1, 0x18, 0xd5, 0xd4, 0x00, 0x8e, 0x9c, 0xec, 0x4f, 0xe5, 0x1d, 0xf8, 0x23, 0x79, + 0xdf, 0x06, 0x88, 0x5a, 0x96, 0x96, 0x91, 0xe9, 0xed, 0x50, 0xa3, 0x42, 0xad, 0xa8, 0x7c, 0x9a, + 0x29, 0xf2, 0x3c, 0x29, 0xfc, 0xc3, 0xb4, 0x11, 0x06, 0x54, 0x8b, 0x76, 0x20, 0x0a, 0x96, 0x66, + 0x8e, 0xb8, 0xaa, 0x77, 0x2d, 0x24, 0x1a, 0xd8, 0x7c, 0xb0, 0x4c, 0x10, 0x33, 0xdb, 0xb5, 0x2e, + 0x30, 0x77, 0xd3, 0x68, 0x20, 0x90, 0xf5, 0x94, 0xe2, 0xe5, 0xda, 0xe6, 0x04, 0xec, 0x49, 0x80, + 0x30, 0xad, 0x86, 0x4d, 0x83, 0x69, 0x2a, 0x11, 0xe8, 0xb9, 0xd5, 0x92, 0xf0, 0x56, 0xb2, 0x89, + 0x52, 0xf2, 0x9b, 0x13, 0x72, 0x51, 0xfc, 0x1a, 0x84, 0xe6, 0x6a, 0x78, 0x1a, 0x4f, 0x2f, 0xb5, + 0xeb, 0xfb, 0x63, 0x88, 0x68, 0xf2, 0xe9, 0xa3, 0x54, 0x53, 0xec, 0x39, 0xf8, 0x3f, 0x1d, 0x58, + 0xe4, 0x1a, 0x25, 0xd1, 0xb9, 0x27, 0x02, 0x4f, 0x5a, 0xc2, 0x29, 0x07, 0xda, 0xa6, 0x97, 0xc4, + 0x37, 0x52, 0xa2, 0x3a, 0x04, 0x0c, 0xdf, 0x75, 0x1f, 0x2e, 0x7e, 0x2f, 0xca, 0x20, 0x25, 0xe6, + 0xa0, 0x55, 0xc9, 0x86, 0x04, 0xb1, 0xa2, 0x2b, 0xc1, 0xb1, 0xdb, 0xd3, 0xf0, 0x91, 0x87, 0x34, + 0x2a, 0x0c, 0x99, 0xcb, 0x5a, 0xd5, 0x27, 0xa6, 0x4d, 0xda, 0xda, 0xbf, 0x6a, 0x93, 0x3a, 0x90, + 0x03, 0x8d, 0x8c, 0xd6, 0xb2, 0xad, 0x6a, 0x8d, 0x9a, 0xb9, 0x01, 0x05, 0xcd, 0x9f, 0x62, 0x90, + 0x86, 0x26, 0xaf, 0xf5, 0x37, 0xc0, 0x8a, 0x8b, 0x57, 0x31, 0x71, 0x9d, 0x01, 0x0e, 0x2d, 0xa0, + 0x19, 0xeb, 0xb1, 0x67, 0x03, 0xae, 0xa7, 0x08, 0x06, 0x7a, 0x80, 0xa0, 0x5d, 0x07, 0x17, 0x63, + 0x2b, 0xe7, 0x45, 0x9e, 0xa5, 0x76, 0xb7, 0xb1, 0x8a, 0x55, 0x4b, 0xaf, 0x21, 0x4e, 0xfd, 0xfa, + 0x2d, 0xf5, 0x9d, 0x57, 0xf3, 0x39, 0xce, 0x44, 0xac, 0x8a, 0x6c, 0xbd, 0xbd, 0x91, 0x8b, 0xae, + 0xa9, 0x7a, 0x18, 0x73, 0xf2, 0x12, 0xc0, 0x5f, 0x85, 0x5b, 0x23, 0xa5, 0x76, 0x98, 0xd9, 0x0a, + 0x39, 0xa8, 0x28, 0xbb, 0x91, 0x7b, 0x61, 0x7a, 0xa1, 0xd0, 0xfe, 0x39, 0xa9, 0x42, 0x9b, 0xb7, + 0x5f, 0x36, 0x91, 0xaa, 0x6e, 0x15, 0xb4, 0x0c, 0x2c, 0xa2, 0x5a, 0x4e, 0x09, 0xe8, 0xf2, 0x1b, + 0x18, 0xe8, 0xa6, 0x3b, 0x1c, 0x41, 0xb5, 0xb3, 0xe8, 0xc0, 0xe7, 0xba, 0x5d, 0x32, 0xaf, 0x15, + 0x2c, 0x25, 0x7f, 0x13, 0xe5, 0x05, 0xcc, 0xd9, 0xc1, 0x8d, 0xa1, 0x01, 0xf3, 0x0a, 0x81, 0x1f, + 0x9b, 0xa3, 0xdf, 0x41, 0xb4, 0x31, 0x9c, 0x00, 0xd1, 0x98, 0x4b, 0x10, 0x6d, 0x89, 0xc7, 0x89, + 0xa5, 0xda, 0x8b, 0x70, 0xb6, 0xe9, 0xf0, 0x07, 0x51, 0xd1, 0xa4, 0x7f, 0x54, 0xcd, 0xa7, 0x64, + 0xf5, 0xe3, 0x5f, 0x51, 0x83, 0x8c, 0x58, 0xb3, 0xa4, 0x54, 0x7f, 0x80, 0x62, 0x2a, 0x8b, 0xb8, + 0x5b, 0x33, 0x12, 0x31, 0x49, 0x8f, 0x16, 0x89, 0x70, 0xdb, 0x74, 0x91, 0x08, 0xeb, 0x84, 0xd1, + 0x83, 0xa3, 0x17, 0x46, 0x09, 0xc2, 0x0c, 0x92, 0x93, 0x1c, 0xa8, 0xc7, 0x0f, 0xf7, 0xf2, 0xfb, + 0x12, 0x51, 0xf7, 0x0d, 0x66, 0xad, 0x2e, 0xfb, 0xed, 0xe9, 0x61, 0xa8, 0x73, 0xef, 0xe0, 0x78, + 0x59, 0xfb, 0x56, 0x89, 0x9a, 0x9c, 0x82, 0x8f, 0x90, 0xe7, 0x3e, 0x11, 0x7f, 0x0d, 0x1f, 0xea, + 0x08, 0xfc, 0x48, 0x5c, 0xfc, 0x6a, 0xe5, 0x9d, 0x67, 0xa4, 0x69, 0x12, 0xdd, 0xc8, 0xa1, 0xbe, + 0x1e, 0x27, 0xda, 0xec, 0x50, 0xa3, 0x21, 0xf6, 0xca, 0x8c, 0x2e, 0x64, 0x0b, 0xa1, 0x85, 0xe2, + 0x0f, 0xb9, 0x39, 0x32, 0xf9, 0x62, 0x73, 0x3e, 0x04, 0xea, 0xb2, 0x35, 0xfc, 0x3a, 0x86, 0xe7, + 0x44, 0x92, 0x84, 0xa2, 0x59, 0x07, 0xec, 0x52, 0x36, 0x29, 0xad, 0x69, 0x41, 0xb1, 0x7b, 0xdd, + 0x39, 0x61, 0x19, 0x51, 0xef, 0xad, 0x63, 0xff, 0x33, 0x2d, 0xae, 0x00, 0xa6, 0x0e, 0x44, 0x8f, + 0x6b, 0x79, 0x01, 0xd9, 0x61, 0xfd, 0xdb, 0xb5, 0x9c, 0xba, 0x28, 0x7b, 0x88, 0x9c, 0x0f, 0x63, + 0xa6, 0xfb, 0x6a, 0x74, 0x28, 0x29, 0xaf, 0x02, 0x12, 0xc4, 0x69, 0xdf, 0x69, 0x33, 0x74, 0xe4, + 0x59, 0xab, 0x91, 0x56, 0x4b, 0x95, 0x4e, 0xc7, 0x49, 0x00, 0x42, 0x4e, 0xc1, 0xb6, 0x89, 0xba, + 0x83, 0x59, 0x83, 0x7e, 0x21, 0xc4, 0x85, 0xbe, 0xf0, 0xbe, 0x7c, 0x75, 0x89, 0xef, 0xf5, 0xd7, + 0x95, 0x62, 0xe7, 0xeb, 0xc3, 0xfc, 0x28, 0xc3, 0xea, 0x23, 0x5b, 0xe2, 0x4f, 0xb6, 0xca, 0x40, + 0xf5, 0x7f, 0x08, 0x85, 0x96, 0x91, 0xba, 0x74, 0xb5, 0x0c, 0xf4, 0x6b, 0x2b, 0x6e, 0x2e, 0x54, + 0x36, 0x89, 0xb2, 0x83, 0x7e, 0xc4, 0xf4, 0xee, 0x86, 0x4c, 0xfa, 0xea, 0x4a, 0x51, 0x54, 0x56, + 0x03, 0xd4, 0x9c, 0x63, 0x99, 0xb9, 0x76, 0x89, 0x34, 0x24, 0x57, 0x4d, 0x74, 0x8d, 0xc5, 0xa7, + 0x0b, 0xcd, 0xaf, 0x2c, 0x92, 0x57, 0x98, 0x26, 0x2b, 0x07, 0x47, 0x6d, 0xdf, 0x11, 0xde, 0xad, + 0x73, 0xce, 0x87, 0xdf, 0x22, 0x28, 0x1f, 0x5b, 0x60, 0xf9, 0xf1, 0xd9, 0xbb, 0xac, 0xf2, 0x14, + 0xcd, 0x5d, 0x29, 0xe2, 0x0d, 0xd6, 0x7c, 0x20, 0xfe, 0x09, 0x15, 0x36, 0x78, 0x80, 0xf6, 0x8c, + 0x5d, 0xe8, 0x3a, 0xd5, 0x5f, 0x44, 0x0a, 0x88, 0x2e, 0x2e, 0x45, 0xd0, 0x46, 0x00, 0x1e, 0xe1, + 0x0c, 0x6d, 0xda, 0x0b, 0xef, 0xd9, 0x50, 0xa1, 0x83, 0xe8, 0xa5, 0x39, 0x76, 0xe3, 0x56, 0x23, + 0x37, 0xd5, 0xa2, 0x84, 0xa6, 0x57, 0xfa, 0x67, 0xcb, 0xfd, 0x81, 0x61, 0x09, 0x85, 0x7e, 0x61, + 0x3d, 0x77, 0x8d, 0x38, 0x33, 0x84, 0xb6, 0xc1, 0xb0, 0x54, 0x10, 0x13, 0x37, 0xd3, 0x91, 0xe5, + 0x9f, 0x82, 0x2d, 0x37, 0x58, 0x5c, 0xdb, 0x51, 0x5b, 0x00, 0x1b, 0xd5, 0xdc, 0xc6, 0x58, 0x1e, + 0x13, 0xeb, 0x22, 0x0e, 0xb4, 0x5f, 0xe1, 0x80, 0xb1, 0xe2, 0xf9, 0x3f, 0x0b, 0x45, 0xdb, 0x8b, + 0x2a, 0xe5, 0x76, 0x53, 0x2c, 0x36, 0xd4, 0x10, 0x2d, 0xea, 0x62, 0x21, 0xa4, 0xe7, 0x70, 0x80, + 0x79, 0x5a, 0xec, 0x04, 0x8f, 0x27, 0x65, 0x8b, 0x19, 0x4a, 0xd8, 0xa1, 0xae, 0x68, 0x07, 0x23, + 0x7c, 0x82, 0xeb, 0x93, 0x37, 0x40, 0x64, 0xb1, 0x3c, 0x98, 0x3c, 0xfa, 0x20, 0x5e, 0xbf, 0x57, + 0x46, 0xc3, 0x78, 0x17, 0x75, 0xdf, 0x0b, 0x5f, 0x33, 0xfb, 0x9c, 0xd2, 0x47, 0x53, 0xff, 0xde, + 0x24, 0xe1, 0x25, 0x06, 0x15, 0x7b, 0x94, 0xad, 0xe8, 0x38, 0x62, 0x83, 0xd8, 0x1a, 0xa1, 0xde, + 0xd9, 0x02, 0x08, 0xc8, 0x41, 0x1d, 0x07, 0xea, 0x99, 0x8c, 0x10, 0xf2, 0xf9, 0x1b, 0x60, 0x18, + 0x97, 0x8a, 0x84, 0xa5, 0x7f, 0xb8, 0x20, 0x36, 0xbe, 0x33, 0x0b, 0x8d, 0xba, 0x97, 0xdf, 0xfe, + 0x01, 0xb0, 0x1e, 0x0a, 0xee, 0x90, 0x05, 0xb6, 0x6f, 0x15, 0xbc, 0x22, 0xc0, 0x34, 0xfe, 0xeb, + 0xda, 0x84, 0x2c, 0xb6, 0xb8, 0xa0, 0xc7, 0x44, 0x2e, 0x82, 0x1c, 0x1b, 0xb2, 0xe4, 0x2d, 0x24, + 0xc0, 0x4b, 0x6e, 0x53, 0x16, 0xa4, 0x6e, 0xd0, 0x27, 0x74, 0x87, 0x4b, 0x08, 0xb4, 0x85, 0xbe, + 0xa0, 0xcc, 0xf5, 0x58, 0x96, 0x31, 0x70, 0x22, 0x24, 0xe6, 0xcc, 0xde, 0xc6, 0x1c, 0xd1, 0x91, + 0xde, 0xbd, 0x65, 0x04, 0x51, 0xd2, 0xfa, 0x2f, 0x2e, 0xdb, 0x90, 0xc8, 0x36, 0x4b, 0xc3, 0x23, + 0x1b, 0x3e, 0xe6, 0x21, 0x8f, 0x35, 0xa7, 0x61, 0xf6, 0xb0, 0x74, 0xf3, 0xfe, 0x27, 0x32, 0x9f, + 0xed, 0x18, 0xb8, 0x2e, 0x00, 0x56, 0x26, 0xdc, 0x60, 0xe5, 0xb7, 0xa6, 0x12, 0x6e, 0x14, 0x58, + 0x31, 0xc3, 0x45, 0xff, 0x75, 0x86, 0x8d, 0x85, 0x50, 0x97, 0x66, 0x6b, 0x04, 0x59, 0x7b, 0xbf, + 0xaa, 0x84, 0x77, 0xb3, 0xdd, 0x90, 0xbb, 0x86, 0xc5, 0x36, 0x8f, 0xb0, 0x7e, 0xe3, 0xaf, 0x49, + 0x47, 0x47, 0x6b, 0x4e, 0xe3, 0x18, 0x45, 0x09, 0x83, 0x0c, 0xc1, 0x5d, 0x96, 0x80, 0x5a, 0xd7, + 0xc9, 0x0a, 0x1b, 0xc8, 0x85, 0xac, 0xf2, 0x61, 0x65, 0x38, 0xdb, 0xef, 0x73, 0x02, 0x40, 0x2e, + 0x74, 0x7c, 0x8d, 0x4a, 0x5c, 0x07, 0x4a, 0xf1, 0xb1, 0x41, 0x10, 0x29, 0xa8, 0x2f, 0x0e, 0xe9, + 0x52, 0x3c, 0x6a, 0xa9, 0x9b, 0x86, 0x9b, 0x5d, 0x66, 0x30, 0x2e, 0x74, 0x25, 0xdb, 0xfb, 0x50, + 0x4b, 0x8e, 0x4e, 0xca, 0x0a, 0x8e, 0xfe, 0x99, 0xfe, 0x86, 0xf6, 0x75, 0x30, 0x60, 0x68, 0x90, + 0xb3, 0x63, 0xbe, 0xb7, 0xd1, 0xe4, 0x4c, 0xe5, 0xc2, 0x1e, 0xb0, 0x10, 0x48, 0x03, 0xeb, 0x1d, + 0xc4, 0xdf, 0x3a, 0x66, 0x8e, 0x3a, 0x18, 0x5f, 0xa9, 0x2c, 0x5f, 0xf8, 0xa3, 0x7b, 0x82, 0x5b, + 0x77, 0x91, 0x28, 0x23, 0x48, 0x11, 0x3d, 0xd8, 0x96, 0x9d, 0xf8, 0x12, 0x5a, 0x6e, 0x50, 0x3c, + 0x20, 0x24, 0x21, 0x88, 0x77, 0x21, 0xf5, 0x27, 0x06, 0xf8, 0xe1, 0x03, 0x38, 0x7e, 0x08, 0x0f, + 0xd5, 0xbf, 0x29, 0x38, 0x10, 0xb3, 0x0a, 0x76, 0x1d, 0x2c, 0xc8, 0x9e, 0xbb, 0x9f, 0x04, 0x7d, + 0x69, 0x57, 0x71, 0x62, 0xfa, 0x91, 0xa3, 0xd1, 0xb0, 0xee, 0x65, 0x81, 0xb7, 0x76, 0xb2, 0x35, + 0x14, 0x43, 0xed, 0x39, 0xe1, 0xb5, 0xab, 0xfc, 0xad, 0xa4, 0x6a, 0x34, 0x23, 0x5e, 0x0f, 0xb2, + 0x42, 0xa7, 0x19, 0x8c, 0x6b, 0x50, 0x67, 0x5d, 0x75, 0xff, 0xa1, 0xb9, 0xb9, 0x4c, 0xb1, 0x83, + 0xa8, 0x8e, 0xb9, 0x8a, 0x0b, 0xd3, 0x24, 0xb6, 0x60, 0xec, 0x50, 0xed, 0x84, 0x16, 0x7d, 0x73, + 0xac, 0x69, 0x2c, 0x43, 0x19, 0xd2, 0x8b, 0xe1, 0xd5, 0x66, 0x4f, 0x06, 0xcd, 0xd9, 0x10, 0xbc, + 0x95, 0xde, 0x5d, 0x47, 0x4d, 0x4a, 0x58, 0xa7, 0x42, 0x71, 0x1a, 0x52, 0x10, 0x20, 0x35, 0x51, + 0xf3, 0x23, 0x1c, 0x50, 0x9f, 0x2f, 0x06, 0x88, 0xf1, 0x5b, 0xec, 0x11, 0xd3, 0xdb, 0x89, 0xa6, + 0x4f, 0x53, 0xda, 0xe7, 0xbb, 0xd6, 0x04, 0xb9, 0x63, 0x96, 0x9c, 0x12, 0x18, 0xba, 0x3f, 0x64, + 0x23, 0x57, 0x1f, 0x97, 0x38, 0xc0, 0x39, 0x38, 0x19, 0x10, 0x2b, 0xbb, 0x8f, 0x7f, 0x9d, 0xc6, + 0x85, 0x7c, 0x6c, 0x06, 0xbd, 0xc0, 0x4e, 0x8f, 0xd3, 0x22, 0x81, 0xaf, 0x3d, 0x79, 0x21, 0x73, + 0x08, 0x71, 0x95, 0xdf, 0x0e, 0xe8, 0x0f, 0xc6, 0x87, 0xab, 0x23, 0x04, 0x9a, 0x20, 0x72, 0x54, + 0x9e, 0x3e, 0x5d, 0x87, 0x6b, 0xf4, 0xb1, 0xf6, 0x64, 0x0b, 0x2e, 0x01, 0x9a, 0x65, 0xa1, 0x22, + 0x6a, 0xa3, 0x66, 0x3d, 0x93, 0xb3, 0x93, 0x2c, 0x86, 0xe6, 0x8d, 0x4f, 0xf3, 0x57, 0xec, 0xb4, + 0xdb, 0x8e, 0x4c, 0xf3, 0x17, 0x44, 0x88, 0xbd, 0xb9, 0xcc, 0xbf, 0xf8, 0xae, 0xe8, 0xa4, 0xa5, + 0x2e, 0xa9, 0x75, 0xc1, 0xbe, 0x49, 0x60, 0xbf, 0x2f, 0x99, 0x2a, 0x6e, 0x0c, 0x07, 0x1e, 0x62, + 0xdb, 0x7f, 0x81, 0xad, 0x5a, 0x8f, 0x7c, 0xe3, 0x67, 0x5c, 0x20, 0x03, 0xeb, 0x67, 0x69, 0x8d, + 0x46, 0x12, 0x31, 0x17, 0x48, 0x85, 0xf8, 0xf2, 0x11, 0xaa, 0xc4, 0x72, 0xc0, 0xbb, 0xa2, 0xd9, + 0x52, 0x88, 0x5c, 0x36, 0xac, 0x97, 0x40, 0x52, 0xe9, 0xf9, 0x23, 0xce, 0x8c, 0xbb, 0x54, 0xca, + 0x13, 0x0b, 0xe0, 0x9c, 0xcd, 0xde, 0x44, 0xca, 0xfc, 0xae, 0x6f, 0x8f, 0xc5, 0x4d, 0xa8, 0x9e, + 0xa0, 0x48, 0xe7, 0xd1, 0xe2, 0x07, 0x6f, 0x8a, 0x82, 0xaf, 0xa1, 0xc8, 0x43, 0xa2, 0xc6, 0xc5, + 0x4f, 0xef, 0x5d, 0x51, 0x13, 0xfb, 0xeb, 0xb8, 0xaf, 0xef, 0xb4, 0x10, 0x15, 0x8e, 0x42, 0x90, + 0xb7, 0x5a, 0x2e, 0xef, 0x23, 0x1f, 0x45, 0x56, 0xd9, 0xcb, 0xf0, 0x37, 0xf1, 0xbf, 0x6d, 0x4d, + 0x2a, 0xb4, 0x55, 0x6d, 0x9f, 0x42, 0x5e, 0x26, 0xc2, 0x44, 0x99, 0x0e, 0x44, 0xf4, 0xb4, 0xf8, + 0x36, 0x16, 0x7e, 0x17, 0xfa, 0xac, 0x9d, 0xa2, 0x76, 0x5c, 0xd4, 0x86, 0x07, 0xbe, 0xb5, 0x6b, + 0xb5, 0x42, 0x66, 0xc6, 0x57, 0xc4, 0xfc, 0x5b, 0xb2, 0x8e, 0x57, 0x04, 0x3a, 0xe1, 0x2f, 0x51, + 0x27, 0xee, 0x18, 0x2c, 0x68, 0x7f, 0x15, 0x2f, 0x51, 0x2c, 0xb4, 0xcd, 0x26, 0xa4, 0x9d, 0xa1, + 0xd2, 0x72, 0x36, 0xbf, 0x6b, 0x05, 0xcf, 0xb0, 0x58, 0x07, 0x1f, 0x83, 0x0e, 0x48, 0x8e, 0x9c, + 0x32, 0x12, 0x04, 0xa3, 0xa3, 0xe7, 0x8d, 0xa3, 0x23, 0xe6, 0x79, 0x06, 0x30, 0x6a, 0x15, 0x5c, + 0xfe, 0xb5, 0x8a, 0xba, 0x78, 0x78, 0xb1, 0x5f, 0x9c, 0x5c, 0xca, 0x39, 0x39, 0x5f, 0x01, 0x13, + 0xe1, 0x50, 0xed, 0x90, 0xfc, 0xdc, 0x99, 0x6c, 0x1a, 0xb9, 0xbb, 0x23, 0x7a, 0x56, 0x71, 0xb3, + 0x0f, 0xf3, 0x41, 0x14, 0xfb, 0x8e, 0x88, 0x34, 0x43, 0x0c, 0x72, 0x97, 0xfb, 0x8e, 0x42, 0x24, + 0x7a, 0xea, 0xac, 0xb6, 0xee, 0xa1, 0x7d, 0xbf, 0xc9, 0xdf, 0xbe, 0xeb, 0xce, 0x50, 0xf7, 0x0e, + 0x76, 0xe1, 0x11, 0x06, 0x4e, 0x24, 0x95, 0x63, 0xe6, 0x94, 0x3f, 0x29, 0x42, 0xd2, 0x6a, 0x22, + 0xc5, 0x26, 0xf4, 0xfb, 0x76, 0x93, 0xf3, 0xf7, 0x6d, 0xb8, 0x3e, 0x70, 0x1c, 0x5c, 0xf1, 0xc2, + 0x07, 0x4d, 0xfe, 0x78, 0x7a, 0x46, 0xd4, 0x69, 0x55, 0x1a, 0x53, 0xa6, 0xee, 0xcd, 0xd7, 0xee, + 0xc1, 0x79, 0x40, 0xf3, 0x4a, 0x48, 0x4f, 0x0b, 0x65, 0x0e, 0x2d, 0x23, 0x3d, 0x96, 0xbe, 0xca, + 0x1a, 0x98, 0xf5, 0x6e, 0x64, 0x7c, 0xac, 0x1b, 0xf2, 0x2e, 0x44, 0xf3, 0x50, 0xc8, 0x86, 0xe6, + 0x31, 0xee, 0x21, 0x40, 0x48, 0xc7, 0xf8, 0x3d, 0xbd, 0x16, 0xc4, 0x54, 0xe1, 0x9e, 0x12, 0x9f, + 0xf3, 0x45, 0xc0, 0x35, 0x30, 0xf3, 0x1c, 0x3f, 0xdc, 0x1d, 0xf8, 0x9f, 0x06, 0x3f, 0x01, 0x8b, + 0xed, 0xa8, 0xf9, 0xca, 0x4b, 0x42, 0xe4, 0x8f, 0x53, 0xb2, 0xb4, 0xbf, 0xa9, 0x55, 0xf8, 0x3f, + 0x2f, 0x7c, 0x25, 0x78, 0x3a, 0xfd, 0x25, 0xbd, 0xd7, 0x2f, 0xd7, 0x29, 0x47, 0x64, 0xa6, 0x7f, + 0x4f, 0x5f, 0x0f, 0xb6, 0x75, 0xb6, 0xbc, 0x33, 0xd4, 0xe4, 0x0a, 0x5e, 0x91, 0xc6, 0x9f, 0x92, + 0xb6, 0x9e, 0x8c, 0x33, 0x50, 0x88, 0xc8, 0x28, 0xcd, 0x8f, 0x50, 0x9b, 0x7c, 0x96, 0x4e, 0x6c, + 0x9d, 0x57, 0x26, 0x3f, 0x3a, 0x95, 0xc2, 0x7a, 0x60, 0xd7, 0xc9, 0x7c, 0xcd, 0xaa, 0xf3, 0xd6, + 0xb0, 0xb5, 0x6e, 0xa2, 0x92, 0xbf, 0x96, 0x16, 0x45, 0xf6, 0xe2, 0x13, 0x18, 0x7c, 0x61, 0xd9, + 0x48, 0xa1, 0x7f, 0x6c, 0xf5, 0x38, 0xb5, 0xf1, 0x73, 0xf8, 0xcd, 0xca, 0x5e, 0x18, 0xba, 0x31, + 0xca, 0x8e, 0xc0, 0xad, 0x91, 0x20, 0xf6, 0xef, 0xf5, 0x6f, 0xac, 0xdf, 0x8c, 0x15, 0x25, 0xbe, + 0x3c, 0xbb, 0xf4, 0x3f, 0x92, 0xfd, 0x9a, 0x04, 0xb0, 0xe2, 0x27, 0x5c, 0x73, 0x1b, 0xd7, 0xc5, + 0xa2, 0x03, 0x6f, 0x83, 0x7d, 0xc6, 0x44, 0x85, 0x62, 0x40, 0xe4, 0x0f, 0x19, 0xac, 0x64, 0x69, + 0x1f, 0x24, 0x03, 0x42, 0x69, 0x36, 0xbf, 0x58, 0x69, 0xf7, 0xec, 0x5d, 0x31, 0xb9, 0x5a, 0x7d, + 0x71, 0x4f, 0x9c, 0x67, 0x89, 0xc4, 0x2e, 0xc4, 0x42, 0x19, 0x20, 0xc0, 0x5a, 0x09, 0x86, 0xce, + 0x93, 0x4f, 0xfc, 0xbe, 0xaa, 0x79, 0xa3, 0x36, 0xdd, 0xf0, 0xad, 0xa7, 0x2a, 0x52, 0x5a, 0xb5, + 0x90, 0x6a, 0x57, 0x90, 0x55, 0x89, 0xfd, 0xb9, 0x1c, 0x88, 0x3e, 0x73, 0x6b, 0x22, 0xa7, 0xcb, + 0xb3, 0xa9, 0x55, 0x82, 0xa4, 0x9d, 0xa9, 0x4f, 0x99, 0x0a, 0x2c, 0x60, 0xdc, 0x27, 0xf8, 0x4c, + 0x99, 0xaa, 0x78, 0x63, 0x70, 0xbc, 0x80, 0xae, 0x42, 0x28, 0xce, 0xea, 0x4d, 0x11, 0x50, 0x26, + 0xaf, 0xf8, 0x48, 0x76, 0xc8, 0xc0, 0xe2, 0xf9, 0x9d, 0xd7, 0xb9, 0x7b, 0x2d, 0x38, 0xd3, 0xe4, + 0x38, 0x8a, 0x00, 0xb8, 0x9b, 0x1d, 0xd2, 0x92, 0xb9, 0x94, 0xa8, 0x6a, 0xb0, 0x5d, 0xb8, 0x50, + 0x65, 0x35, 0xf0, 0xd8, 0xf7, 0xb0, 0x64, 0xc1, 0x4b, 0xa1, 0xb9, 0xc7, 0x60, 0xf6, 0x2e, 0x20, + 0x7f, 0xc9, 0x61, 0x64, 0x8f, 0x2f, 0x68, 0x94, 0x8d, 0x12, 0x0f, 0x29, 0x1c, 0x06, 0xe3, 0x23, + 0x73, 0x49, 0x6c, 0x0c, 0xb1, 0x25, 0x02, 0x79, 0xea, 0x36, 0xcf, 0x2d, 0xc8, 0x54, 0xa5, 0x88, + 0xa6, 0x89, 0x45, 0x35, 0xb6, 0x71, 0x3c, 0x20, 0xee, 0x34, 0x1a, 0x32, 0x37, 0x58, 0x6e, 0x92, + 0xc5, 0xfe, 0x8a, 0x03, 0x72, 0x1d, 0xe2, 0x2e, 0x41, 0x1c, 0xd2, 0x7b, 0x4a, 0xef, 0x3e, 0x53, + 0x4b, 0x5d, 0x36, 0xa3, 0x5a, 0x4b, 0xee, 0x4d, 0xd1, 0x5d, 0x7f, 0x4f, 0x58, 0x3a, 0xf8, 0x76, + 0x46, 0x74, 0x29, 0x85, 0xb1, 0x46, 0x85, 0xa3, 0x8d, 0x7a, 0x34, 0x96, 0x2e, 0xed, 0x67, 0x7d, + 0x48, 0x87, 0x38, 0xe9, 0xdb, 0x9d, 0x26, 0x0b, 0x40, 0xe5, 0xb7, 0xde, 0x64, 0x1d, 0x85, 0x7b, + 0x42, 0xf4, 0xdc, 0x6d, 0xe5, 0x64, 0x8b, 0xb5, 0xea, 0x33, 0x75, 0x40, 0x06, 0xca, 0x88, 0x52, + 0x94, 0x07, 0xd1, 0xbe, 0xa3, 0x1d, 0x08, 0x5e, 0x3b, 0xf8, 0x9e, 0xb9, 0x79, 0x94, 0xb1, 0xbb, + 0x01, 0xb3, 0x71, 0x18, 0x0c, 0x2a, 0x66, 0x67, 0x7c, 0xcf, 0x0e, 0x3d, 0x1c, 0xfd, 0xb6, 0x19, + 0xeb, 0xa6, 0xde, 0xc4, 0xda, 0x43, 0x29, 0xe9, 0xb0, 0xb7, 0x82, 0xbf, 0x3a, 0x87, 0xf1, 0x9e, + 0xff, 0x6d, 0x7b, 0xee, 0xe0, 0x93, 0x30, 0x5c, 0xbf, 0xdf, 0xbd, 0x92, 0x71, 0x29, 0xff, 0x01, + 0x27, 0x4a, 0x7e, 0xff, 0x33, 0xfb, 0xf1, 0x24, 0x84, 0xd0, 0xb5, 0x34, 0xf3, 0x51, 0x5b, 0x0d, + 0x32, 0x69, 0x53, 0x16, 0x73, 0x8e, 0x3b, 0x6f, 0x70, 0x47, 0x80, 0xdc, 0x94, 0xa2, 0x13, 0x4a, + 0x7d, 0x80, 0x30, 0x06, 0xe5, 0xb3, 0x81, 0x84, 0x62, 0xe7, 0x23, 0x70, 0x78, 0xed, 0xb8, 0xb7, + 0x8c, 0xc0, 0x36, 0x7e, 0x0b, 0x66, 0x98, 0x7b, 0x58, 0xc1, 0x74, 0x82, 0xc3, 0xec, 0xd6, 0x80, + 0xcc, 0x80, 0x87, 0x9a, 0x74, 0xf7, 0xe6, 0x45, 0xea, 0x7d, 0x11, 0xe2, 0x11, 0x6e, 0xf8, 0x8e, + 0xcf, 0x03, 0xbd, 0x65, 0xb0, 0x88, 0xc9, 0x66, 0x56, 0xf2, 0xd1, 0x4c, 0x38, 0x11, 0xb1, 0x2e, + 0xf5, 0x15, 0x5b, 0xa5, 0xca, 0x6b, 0x35, 0x4b, 0x63, 0xf4, 0xe1, 0x5f, 0xb6, 0xa8, 0xb2, 0xd2, + 0x5c, 0x4b, 0x74, 0xfc, 0x3e, 0x7c, 0x96, 0x5e, 0xe8, 0x94, 0x25, 0xc4, 0xfb, 0x79, 0x1a, 0x42, + 0x6b, 0xf2, 0x72, 0x4e, 0x0d, 0xb0, 0x5e, 0xb4, 0x5c, 0x3e, 0xe4, 0x72, 0x1a, 0x2b, 0x31, 0x97, + 0x21, 0xe6, 0x38, 0x61, 0x32, 0xea, 0xc3, 0x5f, 0x91, 0x95, 0xb8, 0xa2, 0x33, 0x7a, 0xa5, 0xc6, + 0x2d, 0xfe, 0x38, 0xbd, 0x5d, 0x1a, 0xe6, 0x0d, 0x2a, 0xc6, 0xf6, 0xd3, 0xf2, 0x00, 0x7c, 0xac, + 0xe2, 0x90, 0x8c, 0x11, 0xd3, 0x52, 0x0b, 0x46, 0xcf, 0xb3, 0x72, 0xf9, 0xfa, 0x96, 0xac, 0x0d, + 0x12, 0xaf, 0x4e, 0x55, 0x88, 0x3a, 0x37, 0x38, 0xbe, 0x75, 0x83, 0x6b, 0xc8, 0x8c, 0xe8, 0x28, + 0xe3, 0x4b, 0xca, 0xe2, 0x13, 0xac, 0x7c, 0x43, 0xfc, 0xf3, 0x2a, 0x89, 0xf0, 0x78, 0x2c, 0x76, + 0xd2, 0xd4, 0x74, 0x49, 0x12, 0x64, 0x6e, 0xe3, 0xc8, 0x71, 0x32, 0x20, 0x3c, 0x90, 0x47, 0xeb, + 0xec, 0xbb, 0x09, 0xea, 0x4e, 0x16, 0x27, 0x12, 0x99, 0x95, 0x62, 0xe6, 0x37, 0x18, 0x46, 0xce, + 0x84, 0x2c, 0x56, 0xbe, 0xd1, 0x36, 0x39, 0xff, 0xaa, 0x8d, 0x4a, 0xa6, 0xb4, 0x42, 0x83, 0x67, + 0xb0, 0xc6, 0xdc, 0xe2, 0x08, 0xf1, 0x54, 0x4a, 0x81, 0xf1, 0x07, 0x8a, 0x35, 0xf9, 0xcc, 0x8e, + 0x26, 0xfc, 0x7f, 0xdd, 0x95, 0x42, 0x97, 0x92, 0xdc, 0xf1, 0x80, 0x3a, 0x62, 0x72, 0xc8, 0x69, + 0x1d, 0x61, 0x7f, 0x44, 0xe7, 0x45, 0x71, 0x58, 0xd8, 0x8c, 0xb9, 0x2f, 0xec, 0xe4, 0xc0, 0x03, + 0xe6, 0xc0, 0x86, 0xa0, 0xe2, 0xc8, 0xf1, 0x24, 0x4e, 0xf3, 0xca, 0x2e, 0x49, 0x5a, 0x16, 0x60, + 0x4c, 0xe5, 0xd2, 0x88, 0xd6, 0x16, 0x3b, 0x93, 0x44, 0x14, 0xe9, 0x26, 0xf0, 0x1e, 0x0e, 0x9d, + 0xb1, 0x3f, 0xe7, 0xe3, 0xa3, 0x81, 0x3b, 0x07, 0xe7, 0xe1, 0xdf, 0xd6, 0xe9, 0x86, 0x6f, 0x66, + 0xdc, 0x20, 0xe9, 0x19, 0x07, 0x56, 0xbc, 0x76, 0x91, 0x20, 0x97, 0xc9, 0x7a, 0x70, 0xbd, 0x40, + 0x64, 0x2f, 0xbf, 0x09, 0x33, 0x70, 0x67, 0x49, 0x23, 0x9c, 0x30, 0x1c, 0x28, 0x74, 0x0a, 0xdb, + 0x52, 0x53, 0xf1, 0x31, 0xb8, 0x5e, 0xaa, 0xb0, 0xca, 0x25, 0xda, 0xb2, 0x59, 0x52, 0x75, 0x83, + 0x99, 0xfa, 0x52, 0xd2, 0xf2, 0xeb, 0xaf, 0xc5, 0x1b, 0x94, 0xd6, 0xa3, 0x1c, 0xa0, 0xba, 0x02, + 0xe6, 0x94, 0xa4, 0x85, 0x52, 0x51, 0xb9, 0xeb, 0x09, 0xa4, 0x9b, 0xc3, 0x81, 0xb6, 0xcc, 0x21, + 0x7e, 0x36, 0x78, 0x31, 0x95, 0xa0, 0x9f, 0x4a, 0x96, 0x87, 0x54, 0xef, 0x09, 0x8c, 0x5a, 0x63, + 0xfd, 0x39, 0xa1, 0x18, 0xd5, 0xd4, 0x00, 0x8e, 0x9c, 0xec, 0x4f, 0xe5, 0x1d, 0xf8, 0x23, 0x79, + 0xdf, 0x06, 0x88, 0x5a, 0x96, 0x96, 0x91, 0xe9, 0xed, 0x50, 0xa3, 0x42, 0xad, 0xa8, 0x7c, 0x9a, + 0x29, 0xf2, 0x3c, 0x29, 0xfc, 0xc3, 0xb4, 0x11, 0x06, 0x54, 0x8b, 0x76, 0x20, 0x0a, 0x96, 0x66, + 0x8e, 0xb8, 0xaa, 0x77, 0x2d, 0x24, 0x1a, 0xd8, 0x7c, 0xb0, 0x4c, 0x10, 0x33, 0xdb, 0xb5, 0x2e, + 0x30, 0x77, 0xd3, 0x68, 0x20, 0x90, 0xf5, 0x94, 0xe2, 0xe5, 0xda, 0xe6, 0x04, 0xec, 0x49, 0x80, + 0x30, 0xad, 0x86, 0x4d, 0x83, 0x69, 0x2a, 0x11, 0xe8, 0xb9, 0xd5, 0x92, 0xf0, 0x56, 0xb2, 0x89, + 0x52, 0xf2, 0x9b, 0x13, 0x72, 0x51, 0xfc, 0x1a, 0x84, 0xe6, 0x6a, 0x78, 0x1a, 0x4f, 0x2f, 0xb5, + 0xeb, 0xfb, 0x63, 0x88, 0x68, 0xf2, 0xe9, 0xa3, 0x54, 0x53, 0xec, 0x39, 0xf8, 0x3f, 0x1d, 0x58, + 0xe4, 0x1a, 0x25, 0xd1, 0xb9, 0x27, 0x02, 0x4f, 0x5a, 0xc2, 0x29, 0x07, 0xda, 0xa6, 0x97, 0xc4, + 0x37, 0x52, 0xa2, 0x3a, 0x04, 0x0c, 0xdf, 0x75, 0x1f, 0x2e, 0x7e, 0x2f, 0xca, 0x20, 0x25, 0xe6, + 0xa0, 0x55, 0xc9, 0x86, 0x04, 0xb1, 0xa2, 0x2b, 0xc1, 0xb1, 0xdb, 0xd3, 0xf0, 0x91, 0x87, 0x34, + 0x2a, 0x0c, 0x99, 0xcb, 0x5a, 0xd5, 0x27, 0xa6, 0x4d, 0xda, 0xda, 0xbf, 0x6a, 0x93, 0x3a, 0x90, + 0x03, 0x8d, 0x8c, 0xd6, 0xb2, 0xad, 0x6a, 0x8d, 0x9a, 0xb9, 0x01, 0x05, 0xcd, 0x9f, 0x62, 0x90, + 0x86, 0x26, 0xaf, 0xf5, 0x37, 0xc0, 0x8a, 0x8b, 0x57, 0x31, 0x71, 0x9d, 0x01, 0x0e, 0x2d, 0xa0, + 0x19, 0xeb, 0xb1, 0x67, 0x03, 0xae, 0xa7, 0x08, 0x06, 0x7a, 0x80, 0xa0, 0x5d, 0x07, 0x17, 0x63, + 0x2b, 0xe7, 0x45, 0x9e, 0xa5, 0x76, 0xb7, 0xb1, 0x8a, 0x55, 0x4b, 0xaf, 0x21, 0x4e, 0xfd, 0xfa, + 0x2d, 0xf5, 0x9d, 0x57, 0xf3, 0x39, 0xce, 0x44, 0xac, 0x8a, 0x6c, 0xbd, 0xbd, 0x91, 0x8b, 0xae, + 0xa9, 0x7a, 0x18, 0x73, 0xf2, 0x12, 0xc0, 0x5f, 0x85, 0x5b, 0x23, 0xa5, 0x76, 0x98, 0xd9, 0x0a, + 0x39, 0xa8, 0x28, 0xbb, 0x91, 0x7b, 0x61, 0x7a, 0xa1, 0xd0, 0xfe, 0x39, 0xa9, 0x42, 0x9b, 0xb7, + 0x5f, 0x36, 0x91, 0xaa, 0x6e, 0x15, 0xb4, 0x0c, 0x2c, 0xa2, 0x5a, 0x4e, 0x09, 0xe8, 0xf2, 0x1b, + 0x18, 0xe8, 0xa6, 0x3b, 0x1c, 0x41, 0xb5, 0xb3, 0xe8, 0xc0, 0xe7, 0xba, 0x5d, 0x32, 0xaf, 0x15, + 0x2c, 0x25, 0x7f, 0x13, 0xe5, 0x05, 0xcc, 0xd9, 0xc1, 0x8d, 0xa1, 0x01, 0xf3, 0x0a, 0x81, 0x1f, + 0x9b, 0xa3, 0xdf, 0x41, 0xb4, 0x31, 0x9c, 0x00, 0xd1, 0x98, 0x4b, 0x10, 0x6d, 0x89, 0xc7, 0x89, + 0xa5, 0xda, 0x8b, 0x70, 0xb6, 0xe9, 0xf0, 0x07, 0x51, 0xd1, 0xa4, 0x7f, 0x54, 0xcd, 0xa7, 0x64, + 0xf5, 0xe3, 0x5f, 0x51, 0x83, 0x8c, 0x58, 0xb3, 0xa4, 0x54, 0x7f, 0x80, 0x62, 0x2a, 0x8b, 0xb8, + 0x5b, 0x33, 0x12, 0x31, 0x49, 0x8f, 0x16, 0x89, 0x70, 0xdb, 0x74, 0x91, 0x08, 0xeb, 0x84, 0xd1, + 0x83, 0xa3, 0x17, 0x46, 0x09, 0xc2, 0x0c, 0x92, 0x93, 0x1c, 0xa8, 0xc7, 0x0f, 0xf7, 0xf2, 0xfb, + 0x12, 0x51, 0xf7, 0x0d, 0x66, 0xad, 0x2e, 0xfb, 0xed, 0xe9, 0x61, 0xa8, 0x73, 0xef, 0xe0, 0x78, + 0x59, 0xfb, 0x56, 0x89, 0x9a, 0x9c, 0x82, 0x8f, 0x90, 0xe7, 0x3e, 0x11, 0x7f, 0x0d, 0x1f, 0xea, + 0x08, 0xfc, 0x48, 0x5c, 0xfc, 0x6a, 0xe5, 0x9d, 0x67, 0xa4, 0x69, 0x12, 0xdd, 0xc8, 0xa1, 0xbe, + 0x1e, 0x27, 0xda, 0xec, 0x50, 0xa3, 0x21, 0xf6, 0xca, 0x8c, 0x2e, 0x64, 0x0b, 0xa1, 0x85, 0xe2, + 0x0f, 0xb9, 0x39, 0x32, 0xf9, 0x62, 0x73, 0x3e, 0x04, 0xea, 0xb2, 0x35, 0xfc, 0x3a, 0x86, 0xe7, + 0x44, 0x92, 0x84, 0xa2, 0x59, 0x07, 0xec, 0x52, 0x36, 0x29, 0xad, 0x69, 0x41, 0xb1, 0x7b, 0xdd, + 0x39, 0x61, 0x19, 0x51, 0xef, 0xad, 0x63, 0xff, 0x33, 0x2d, 0xae, 0x00, 0xa6, 0x0e, 0x44, 0x8f, + 0x6b, 0x79, 0x01, 0xd9, 0x61, 0xfd, 0xdb, 0xb5, 0x9c, 0xba, 0x28, 0x7b, 0x88, 0x9c, 0x0f, 0x63, + 0xa6, 0xfb, 0x6a, 0x74, 0x28, 0x29, 0xaf, 0x02, 0x12, 0xc4, 0x69, 0xdf, 0x69, 0x33, 0x74, 0xe4, + 0x59, 0xab, 0x91, 0x56, 0x4b, 0x95, 0x4e, 0xc7, 0x49, 0x00, 0x42, 0x4e, 0xc1, 0xb6, 0x89, 0xba, + 0x83, 0x59, 0x83, 0x7e, 0x21, 0xc4, 0x85, 0xbe, 0xf0, 0xbe, 0x7c, 0x75, 0x89, 0xef, 0xf5, 0xd7, + 0x95, 0x62, 0xe7, 0xeb, 0xc3, 0xfc, 0x28, 0xc3, 0xea, 0x23, 0x5b, 0xe2, 0x4f, 0xb6, 0xca, 0x40, + 0xf5, 0x7f, 0x08, 0x85, 0x96, 0x91, 0xba, 0x74, 0xb5, 0x0c, 0xf4, 0x6b, 0x2b, 0x6e, 0x2e, 0x54, + 0x36, 0x89, 0xb2, 0x83, 0x7e, 0xc4, 0xf4, 0xee, 0x86, 0x4c, 0xfa, 0xea, 0x4a, 0x51, 0x54, 0x56, + 0x03, 0xd4, 0x9c, 0x63, 0x99, 0xb9, 0x76, 0x89, 0x34, 0x24, 0x57, 0x4d, 0x74, 0x8d, 0xc5, 0xa7, + 0x0b, 0xcd, 0xaf, 0x2c, 0x92, 0x57, 0x98, 0x26, 0x2b, 0x07, 0x47, 0x6d, 0xdf, 0x11, 0xde, 0xad, + 0x73, 0xce, 0x87, 0xdf, 0x22, 0x28, 0x1f, 0x5b, 0x60, 0xf9, 0xf1, 0xd9, 0xbb, 0xac, 0xf2, 0x14, + 0xcd, 0x5d, 0x29, 0xe2, 0x0d, 0xd6, 0x7c, 0x20, 0xfe, 0x09, 0x15, 0x36, 0x78, 0x80, 0xf6, 0x8c, + 0xb2, 0x8a, 0x3b, 0x40, 0x1d, 0x2a, 0x6a, 0x62, 0xb6, 0x04, 0xba, 0x6d, 0xa5, 0x68, 0x0e, 0xc5, + 0xb9, 0xdb, 0x69, 0x6c, 0xb2, 0xc3, 0xb4, 0xf3, 0x06, 0x2c, 0x07, 0x72, 0xd9, 0x4e, 0xeb, 0xb4, + 0xa2, 0xf9, 0xcd, 0x52, 0xdc, 0xba, 0xba, 0xa6, 0xc0, 0xb0, 0x09, 0xa4, 0xab, 0xa9, 0xd4, 0x7c, + 0x38, 0x45, 0xb6, 0xd0, 0x7b, 0x0e, 0x9e, 0xe9, 0x48, 0xe5, 0x0e, 0xc7, 0xaa, 0xe6, 0xc0, 0xc0, + 0x91, 0xa7, 0xb8, 0x09, 0xbb, 0xf5, 0x1c, 0x5d, 0xf5, 0x12, 0x01, 0x8d, 0xf2, 0x3b, 0x1e, 0x7b, + 0x39, 0x7c, 0xc3, 0x3f, 0x79, 0xdf, 0xa0, 0x83, 0x66, 0x20, 0xa2, 0x26, 0x34, 0xac, 0xc9, 0x5b, + 0x73, 0x86, 0xc6, 0xe0, 0xc9, 0xfc, 0x82, 0xce, 0x40, 0x81, 0xbc, 0xfd, 0x4d, 0x97, 0x0a, 0xab, + 0x05, 0xd5, 0xa6, 0xf6, 0xa4, 0xc6, 0x3d, 0xa6, 0x4e, 0xa6, 0x7b, 0x1d, 0xd5, 0x98, 0x47, 0x20, + 0x7c, 0x82, 0xeb, 0x93, 0x37, 0x40, 0x64, 0xb1, 0x3c, 0x98, 0x3c, 0xfa, 0x20, 0x5e, 0xbf, 0x57, + 0x46, 0xc3, 0x78, 0x17, 0x75, 0xdf, 0x0b, 0x5f, 0x33, 0xfb, 0x9c, 0xd2, 0x47, 0x53, 0xff, 0xde, + 0x24, 0xe1, 0x25, 0x06, 0x15, 0x7b, 0x94, 0xad, 0xe8, 0x38, 0x62, 0x83, 0xd8, 0x1a, 0xa1, 0xde, + 0xd9, 0x02, 0x08, 0xc8, 0x41, 0x1d, 0x07, 0xea, 0x99, 0x8c, 0x10, 0xf2, 0xf9, 0x1b, 0x60, 0x18, + 0x97, 0x8a, 0x84, 0xa5, 0x7f, 0xb8, 0x20, 0x36, 0xbe, 0x33, 0x0b, 0x8d, 0xba, 0x97, 0xdf, 0xfe, + 0x01, 0xb0, 0x1e, 0x0a, 0xee, 0x90, 0x05, 0xb6, 0x6f, 0x15, 0xbc, 0x22, 0xc0, 0x34, 0xfe, 0xeb, + 0xda, 0x84, 0x2c, 0xb6, 0xb8, 0xa0, 0xc7, 0x44, 0x2e, 0x82, 0x1c, 0x1b, 0xb2, 0xe4, 0x2d, 0x24, + 0xc0, 0x4b, 0x6e, 0x53, 0x16, 0xa4, 0x6e, 0xd0, 0x27, 0x74, 0x87, 0x4b, 0x08, 0xb4, 0x85, 0xbe, + 0xa0, 0xcc, 0xf5, 0x58, 0x96, 0x31, 0x70, 0x22, 0x24, 0xe6, 0xcc, 0xde, 0xc6, 0x1c, 0xd1, 0x91, + 0xde, 0xbd, 0x65, 0x04, 0x51, 0xd2, 0xfa, 0x2f, 0x2e, 0xdb, 0x90, 0xc8, 0x36, 0x4b, 0xc3, 0x23, + 0x1b, 0x3e, 0xe6, 0x21, 0x8f, 0x35, 0xa7, 0x61, 0xf6, 0xb0, 0x74, 0xf3, 0xfe, 0x27, 0x32, 0x9f, + 0xed, 0x18, 0xb8, 0x2e, 0x00, 0x56, 0x26, 0xdc, 0x60, 0xe5, 0xb7, 0xa6, 0x12, 0x6e, 0x14, 0x58, + 0x31, 0xc3, 0x45, 0xff, 0x75, 0x86, 0x8d, 0x85, 0x50, 0x97, 0x66, 0x6b, 0x04, 0x59, 0x7b, 0xbf, + 0xaa, 0x84, 0x77, 0xb3, 0xdd, 0x90, 0xbb, 0x86, 0xc5, 0x36, 0x8f, 0xb0, 0x7e, 0xe3, 0xaf, 0x49, + 0x47, 0x47, 0x6b, 0x4e, 0xe3, 0x18, 0x45, 0x09, 0x83, 0x0c, 0xc1, 0x5d, 0x96, 0x80, 0x5a, 0xd7, + 0xc9, 0x0a, 0x1b, 0xc8, 0x85, 0xac, 0xf2, 0x61, 0x65, 0x38, 0xdb, 0xef, 0x73, 0x02, 0x40, 0x2e, + 0x74, 0x7c, 0x8d, 0x4a, 0x5c, 0x07, 0x4a, 0xf1, 0xb1, 0x41, 0x10, 0x29, 0xa8, 0x2f, 0x0e, 0xe9, + 0x52, 0x3c, 0x6a, 0xa9, 0x9b, 0x86, 0x9b, 0x5d, 0x66, 0x30, 0x2e, 0x74, 0x25, 0xdb, 0xfb, 0x50, + 0x4b, 0x8e, 0x4e, 0xca, 0x0a, 0x8e, 0xfe, 0x99, 0xfe, 0x86, 0xf6, 0x75, 0x30, 0x60, 0x68, 0x90, + 0xb3, 0x63, 0xbe, 0xb7, 0xd1, 0xe4, 0x4c, 0xe5, 0xc2, 0x1e, 0xb0, 0x10, 0x48, 0x03, 0xeb, 0x1d, + 0xc4, 0xdf, 0x3a, 0x66, 0x8e, 0x3a, 0x18, 0x5f, 0xa9, 0x2c, 0x5f, 0xf8, 0xa3, 0x7b, 0x82, 0x5b, + 0x77, 0x91, 0x28, 0x23, 0x48, 0x11, 0x3d, 0xd8, 0x96, 0x9d, 0xf8, 0x12, 0x5a, 0x6e, 0x50, 0x3c, + 0x20, 0x24, 0x21, 0x88, 0x77, 0x21, 0xf5, 0x27, 0x06, 0xf8, 0xe1, 0x03, 0x38, 0x7e, 0x08, 0x0f, + 0xd5, 0xbf, 0x29, 0x38, 0x10, 0xb3, 0x0a, 0x76, 0x1d, 0x2c, 0xc8, 0x9e, 0xbb, 0x9f, 0x04, 0x7d, + 0x69, 0x57, 0x71, 0x62, 0xfa, 0x91, 0xa3, 0xd1, 0xb0, 0xee, 0x65, 0x81, 0xb7, 0x76, 0xb2, 0x35, + 0x14, 0x43, 0xed, 0x39, 0xe1, 0xb5, 0xab, 0xfc, 0xad, 0xa4, 0x6a, 0x34, 0x23, 0x5e, 0x0f, 0xb2, + 0x42, 0xa7, 0x19, 0x8c, 0x6b, 0x50, 0x67, 0x5d, 0x75, 0xff, 0xa1, 0xb9, 0xb9, 0x4c, 0xb1, 0x83, + 0xa8, 0x8e, 0xb9, 0x8a, 0x0b, 0xd3, 0x24, 0xb6, 0x60, 0xec, 0x50, 0xed, 0x84, 0x16, 0x7d, 0x73, + 0xac, 0x69, 0x2c, 0x43, 0x19, 0xd2, 0x8b, 0xe1, 0xd5, 0x66, 0x4f, 0x06, 0xcd, 0xd9, 0x10, 0xbc, + 0x95, 0xde, 0x5d, 0x47, 0x4d, 0x4a, 0x58, 0xa7, 0x42, 0x71, 0x1a, 0x52, 0x10, 0x20, 0x35, 0x51, + 0xf3, 0x23, 0x1c, 0x50, 0x9f, 0x2f, 0x06, 0x88, 0xf1, 0x5b, 0xec, 0x11, 0xd3, 0xdb, 0x89, 0xa6, + 0x4f, 0x53, 0xda, 0xe7, 0xbb, 0xd6, 0x04, 0xb9, 0x63, 0x96, 0x9c, 0x12, 0x18, 0xba, 0x3f, 0x64, + 0x23, 0x57, 0x1f, 0x97, 0x38, 0xc0, 0x39, 0x38, 0x19, 0x10, 0x2b, 0xbb, 0x8f, 0x7f, 0x9d, 0xc6, + 0x85, 0x7c, 0x6c, 0x06, 0xbd, 0xc0, 0x4e, 0x8f, 0xd3, 0x22, 0x81, 0xaf, 0x3d, 0x79, 0x21, 0x73, + 0x08, 0x71, 0x95, 0xdf, 0x0e, 0xe8, 0x0f, 0xc6, 0x87, 0xab, 0x23, 0x04, 0x9a, 0x20, 0x72, 0x54, + 0x9e, 0x3e, 0x5d, 0x87, 0x6b, 0xf4, 0xb1, 0xf6, 0x64, 0x0b, 0x2e, 0x01, 0x9a, 0x65, 0xa1, 0x22, + 0x6a, 0xa3, 0x66, 0x3d, 0x93, 0xb3, 0x93, 0x2c, 0x86, 0xe6, 0x8d, 0x4f, 0xf3, 0x57, 0xec, 0xb4, + 0xdb, 0x8e, 0x4c, 0xf3, 0x17, 0x44, 0x88, 0xbd, 0xb9, 0xcc, 0xbf, 0xf8, 0xae, 0xe8, 0xa4, 0xa5, + 0x2e, 0xa9, 0x75, 0xc1, 0xbe, 0x49, 0x60, 0xbf, 0x2f, 0x99, 0x2a, 0x6e, 0x0c, 0x07, 0x1e, 0x62, + 0xdb, 0x7f, 0x81, 0xad, 0x5a, 0x8f, 0x7c, 0xe3, 0x67, 0x5c, 0x20, 0x03, 0xeb, 0x67, 0x69, 0x8d, + 0x46, 0x12, 0x31, 0x17, 0x48, 0x85, 0xf8, 0xf2, 0x11, 0xaa, 0xc4, 0x72, 0xc0, 0xbb, 0xa2, 0xd9, + 0x52, 0x88, 0x5c, 0x36, 0xac, 0x97, 0x40, 0x52, 0xe9, 0xf9, 0x23, 0xce, 0x8c, 0xbb, 0x54, 0xca, + 0x13, 0x0b, 0xe0, 0x9c, 0xcd, 0xde, 0x44, 0xca, 0xfc, 0xae, 0x6f, 0x8f, 0xc5, 0x4d, 0xa8, 0x9e, + 0xa0, 0x48, 0xe7, 0xd1, 0xe2, 0x07, 0x6f, 0x8a, 0x82, 0xaf, 0xa1, 0xc8, 0x43, 0xa2, 0xc6, 0xc5, + 0x4f, 0xef, 0x5d, 0x51, 0x13, 0xfb, 0xeb, 0xb8, 0xaf, 0xef, 0xb4, 0x10, 0x15, 0x8e, 0x42, 0x90, + 0xb7, 0x5a, 0x2e, 0xef, 0x23, 0x1f, 0x45, 0x56, 0xd9, 0xcb, 0xf0, 0x37, 0xf1, 0xbf, 0x6d, 0x4d, + 0x2a, 0xb4, 0x55, 0x6d, 0x9f, 0x42, 0x5e, 0x26, 0xc2, 0x44, 0x99, 0x0e, 0x44, 0xf4, 0xb4, 0xf8, + 0x36, 0x16, 0x7e, 0x17, 0xfa, 0xac, 0x9d, 0xa2, 0x76, 0x5c, 0xd4, 0x86, 0x07, 0xbe, 0xb5, 0x6b, + 0xb5, 0x42, 0x66, 0xc6, 0x57, 0xc4, 0xfc, 0x5b, 0xb2, 0x8e, 0x57, 0x04, 0x3a, 0xe1, 0x2f, 0x51, + 0x27, 0xee, 0x18, 0x2c, 0x68, 0x7f, 0x15, 0x2f, 0x51, 0x2c, 0xb4, 0xcd, 0x26, 0xa4, 0x9d, 0xa1, + 0xd2, 0x72, 0x36, 0xbf, 0x6b, 0x05, 0xcf, 0xb0, 0x58, 0x07, 0x1f, 0x83, 0x0e, 0x48, 0x8e, 0x9c, + 0x32, 0x12, 0x04, 0xa3, 0xa3, 0xe7, 0x8d, 0xa3, 0x23, 0xe6, 0x79, 0x06, 0x30, 0x6a, 0x15, 0x5c, + 0xfe, 0xb5, 0x8a, 0xba, 0x78, 0x78, 0xb1, 0x5f, 0x9c, 0x5c, 0xca, 0x39, 0x39, 0x5f, 0x01, 0x13, + 0xe1, 0x50, 0xed, 0x90, 0xfc, 0xdc, 0x99, 0x6c, 0x1a, 0xb9, 0xbb, 0x23, 0x7a, 0x56, 0x71, 0xb3, + 0x0f, 0xf3, 0x41, 0x14, 0xfb, 0x8e, 0x88, 0x34, 0x43, 0x0c, 0x72, 0x97, 0xfb, 0x8e, 0x42, 0x24, + 0x7a, 0xea, 0xac, 0xb6, 0xee, 0xa1, 0x7d, 0xbf, 0xc9, 0xdf, 0xbe, 0xeb, 0xce, 0x50, 0xf7, 0x0e, + 0x76, 0xe1, 0x11, 0x06, 0x4e, 0x24, 0x95, 0x63, 0xe6, 0x94, 0x3f, 0x29, 0x42, 0xd2, 0x6a, 0x22, + 0xc5, 0x26, 0xf4, 0xfb, 0x76, 0x93, 0xf3, 0xf7, 0x6d, 0xb8, 0x3e, 0x70, 0x1c, 0x5c, 0xf1, 0xc2, + 0x07, 0x4d, 0xfe, 0x78, 0x7a, 0x46, 0xd4, 0x69, 0x55, 0x1a, 0x53, 0xa6, 0xee, 0xcd, 0xd7, 0xee, + 0xc1, 0x79, 0x40, 0xf3, 0x4a, 0x48, 0x4f, 0x0b, 0x65, 0x0e, 0x2d, 0x23, 0x3d, 0x96, 0xbe, 0xca, + 0x1a, 0x98, 0xf5, 0x6e, 0x64, 0x7c, 0xac, 0x1b, 0xf2, 0x2e, 0x44, 0xf3, 0x50, 0xc8, 0x86, 0xe6, + 0x31, 0xee, 0x21, 0x40, 0x48, 0xc7, 0xf8, 0x3d, 0xbd, 0x16, 0xc4, 0x54, 0xe1, 0x9e, 0x12, 0x9f, + 0xf3, 0x45, 0xc0, 0x35, 0x30, 0xf3, 0x1c, 0x3f, 0xdc, 0x1d, 0xf8, 0x9f, 0x06, 0x3f, 0x01, 0x8b, + 0xed, 0xa8, 0xf9, 0xca, 0x4b, 0x42, 0xe4, 0x8f, 0x53, 0xb2, 0xb4, 0xbf, 0xa9, 0x55, 0xf8, 0x3f, + 0x2f, 0x7c, 0x25, 0x78, 0x3a, 0xfd, 0x25, 0xbd, 0xd7, 0x2f, 0xd7, 0x29, 0x47, 0x64, 0xa6, 0x7f, + 0x4f, 0x5f, 0x0f, 0xb6, 0x75, 0xb6, 0xbc, 0x33, 0xd4, 0xe4, 0x0a, 0x5e, 0x91, 0xc6, 0x9f, 0x92, + 0xb6, 0x9e, 0x8c, 0x33, 0x50, 0x88, 0xc8, 0x28, 0xcd, 0x8f, 0x50, 0x9b, 0x7c, 0x96, 0x4e, 0x6c, + 0x9d, 0x57, 0x26, 0x3f, 0x3a, 0x95, 0xc2, 0x7a, 0x60, 0xd7, 0xc9, 0x7c, 0xcd, 0xaa, 0xf3, 0xd6, + 0xb0, 0xb5, 0x6e, 0xa2, 0x92, 0xbf, 0x96, 0x16, 0x45, 0xf6, 0xe2, 0x13, 0x18, 0x7c, 0x61, 0xd9, + 0x48, 0xa1, 0x7f, 0x6c, 0xf5, 0x38, 0xb5, 0xf1, 0x73, 0xf8, 0xcd, 0xca, 0x5e, 0x18, 0xba, 0x31, + 0xca, 0x8e, 0xc0, 0xad, 0x91, 0x20, 0xf6, 0xef, 0xf5, 0x6f, 0xac, 0xdf, 0x8c, 0x15, 0x25, 0xbe, + 0x3c, 0xbb, 0xf4, 0x3f, 0x92, 0xfd, 0x9a, 0x04, 0xb0, 0xe2, 0x27, 0x5c, 0x73, 0x1b, 0xd7, 0xc5, + 0xa2, 0x03, 0x6f, 0x83, 0x7d, 0xc6, 0x44, 0x85, 0x62, 0x40, 0xe4, 0x0f, 0x19, 0xac, 0x64, 0x69, + 0x1f, 0x24, 0x03, 0x42, 0x69, 0x36, 0xbf, 0x58, 0x69, 0xf7, 0xec, 0x5d, 0x31, 0xb9, 0x5a, 0x7d, + 0x71, 0x4f, 0x9c, 0x67, 0x89, 0xc4, 0x2e, 0xc4, 0x42, 0x19, 0x20, 0xc0, 0x5a, 0x09, 0x86, 0xce, + 0x93, 0x4f, 0xfc, 0xbe, 0xaa, 0x79, 0xa3, 0x36, 0xdd, 0xf0, 0xad, 0xa7, 0x2a, 0x52, 0x5a, 0xb5, + 0x90, 0x6a, 0x57, 0x90, 0x55, 0x89, 0xfd, 0xb9, 0x1c, 0x88, 0x3e, 0x73, 0x6b, 0x22, 0xa7, 0xcb, + 0xb3, 0xa9, 0x55, 0x82, 0xa4, 0x9d, 0xa9, 0x4f, 0x99, 0x0a, 0x2c, 0x60, 0xdc, 0x27, 0xf8, 0x4c, + 0x99, 0xaa, 0x78, 0x63, 0x70, 0xbc, 0x80, 0xae, 0x42, 0x28, 0xce, 0xea, 0x4d, 0x11, 0x50, 0x26, + 0xaf, 0xf8, 0x48, 0x76, 0xc8, 0xc0, 0xe2, 0xf9, 0x9d, 0xd7, 0xb9, 0x7b, 0x2d, 0x38, 0xd3, 0xe4, + 0x38, 0x8a, 0x00, 0xb8, 0x9b, 0x1d, 0xd2, 0x92, 0xb9, 0x94, 0xa8, 0x6a, 0xb0, 0x5d, 0xb8, 0x50, + 0x65, 0x35, 0xf0, 0xd8, 0xf7, 0xb0, 0x64, 0xc1, 0x4b, 0xa1, 0xb9, 0xc7, 0x60, 0xf6, 0x2e, 0x20, + 0x7f, 0xc9, 0x61, 0x64, 0x8f, 0x2f, 0x68, 0x94, 0x8d, 0x12, 0x0f, 0x29, 0x1c, 0x06, 0xe3, 0x23, + 0x73, 0x49, 0x6c, 0x0c, 0xb1, 0x25, 0x02, 0x79, 0xea, 0x36, 0xcf, 0x2d, 0xc8, 0x54, 0xa5, 0x88, + 0xa6, 0x89, 0x45, 0x35, 0xb6, 0x71, 0x3c, 0x20, 0xee, 0x34, 0x1a, 0x32, 0x37, 0x58, 0x6e, 0x92, + 0xc5, 0xfe, 0x8a, 0x03, 0x72, 0x1d, 0xe2, 0x2e, 0x41, 0x1c, 0xd2, 0x7b, 0x4a, 0xef, 0x3e, 0x53, + 0x4b, 0x5d, 0x36, 0xa3, 0x5a, 0x4b, 0xee, 0x4d, 0xd1, 0x5d, 0x7f, 0x4f, 0x58, 0x3a, 0xf8, 0x76, + 0x46, 0x74, 0x29, 0x85, 0xb1, 0x46, 0x85, 0xa3, 0x8d, 0x7a, 0x34, 0x96, 0x2e, 0xed, 0x67, 0x7d, + 0x48, 0x87, 0x38, 0xe9, 0xdb, 0x9d, 0x26, 0x0b, 0x40, 0xe5, 0xb7, 0xde, 0x64, 0x1d, 0x85, 0x7b, + 0x42, 0xf4, 0xdc, 0x6d, 0xe5, 0x64, 0x8b, 0xb5, 0xea, 0x33, 0x75, 0x40, 0x06, 0xca, 0x88, 0x52, + 0x94, 0x07, 0xd1, 0xbe, 0xa3, 0x1d, 0x08, 0x5e, 0x3b, 0xf8, 0x9e, 0xb9, 0x79, 0x94, 0xb1, 0xbb, + 0x01, 0xb3, 0x71, 0x18, 0x0c, 0x2a, 0x66, 0x67, 0x7c, 0xcf, 0x0e, 0x3d, 0x1c, 0xfd, 0xb6, 0x19, + 0xeb, 0xa6, 0xde, 0xc4, 0xda, 0x43, 0x29, 0xe9, 0xb0, 0xb7, 0x82, 0xbf, 0x3a, 0x87, 0xf1, 0x9e, + 0xff, 0x6d, 0x7b, 0xee, 0xe0, 0x93, 0x30, 0x5c, 0xbf, 0xdf, 0xbd, 0x92, 0x71, 0x29, 0xff, 0x01, + 0x27, 0x4a, 0x7e, 0xff, 0x33, 0xfb, 0xf1, 0x24, 0x84, 0xd0, 0xb5, 0x34, 0xf3, 0x51, 0x5b, 0x0d, + 0x32, 0x69, 0x53, 0x16, 0x73, 0x8e, 0x3b, 0x6f, 0x70, 0x47, 0x80, 0xdc, 0x94, 0xa2, 0x13, 0x4a, + 0x7d, 0x80, 0x30, 0x06, 0xe5, 0xb3, 0x81, 0x84, 0x62, 0xe7, 0x23, 0x70, 0x78, 0xed, 0xb8, 0xb7, + 0x8c, 0xc0, 0x36, 0x7e, 0x0b, 0x66, 0x98, 0x7b, 0x58, 0xc1, 0x74, 0x82, 0xc3, 0xec, 0xd6, 0x80, + 0xcc, 0x80, 0x87, 0x9a, 0x74, 0xf7, 0xe6, 0x45, 0xea, 0x7d, 0x11, 0xe2, 0x11, 0x6e, 0xf8, 0x8e, + 0xcf, 0x03, 0xbd, 0x65, 0xb0, 0x88, 0xc9, 0x66, 0x56, 0xf2, 0xd1, 0x4c, 0x38, 0x11, 0xb1, 0x2e, + 0xf5, 0x15, 0x5b, 0xa5, 0xca, 0x6b, 0x35, 0x4b, 0x63, 0xf4, 0xe1, 0x5f, 0xb6, 0xa8, 0xb2, 0xd2, + 0x5c, 0x4b, 0x74, 0xfc, 0x3e, 0x7c, 0x96, 0x5e, 0xe8, 0x94, 0x25, 0xc4, 0xfb, 0x79, 0x1a, 0x42, + 0x6b, 0xf2, 0x72, 0x4e, 0x0d, 0xb0, 0x5e, 0xb4, 0x5c, 0x3e, 0xe4, 0x72, 0x1a, 0x2b, 0x31, 0x97, + 0x21, 0xe6, 0x38, 0x61, 0x32, 0xea, 0xc3, 0x5f, 0x91, 0x95, 0xb8, 0xa2, 0x33, 0x7a, 0xa5, 0xc6, + 0x2d, 0xfe, 0x38, 0xbd, 0x5d, 0x1a, 0xe6, 0x0d, 0x2a, 0xc6, 0xf6, 0xd3, 0xf2, 0x00, 0x7c, 0xac, + 0xe2, 0x90, 0x8c, 0x11, 0xd3, 0x52, 0x0b, 0x46, 0xcf, 0xb3, 0x72, 0xf9, 0xfa, 0x96, 0xac, 0x0d, + 0x12, 0xaf, 0x4e, 0x55, 0x88, 0x3a, 0x37, 0x38, 0xbe, 0x75, 0x83, 0x6b, 0xc8, 0x8c, 0xe8, 0x28, + 0xe3, 0x4b, 0xca, 0xe2, 0x13, 0xac, 0x7c, 0x43, 0xfc, 0xf3, 0x2a, 0x89, 0xf0, 0x78, 0x2c, 0x76, + 0xd2, 0xd4, 0x74, 0x49, 0x12, 0x64, 0x6e, 0xe3, 0xc8, 0x71, 0x32, 0x20, 0x3c, 0x90, 0x47, 0xeb, + 0xec, 0xbb, 0x09, 0xea, 0x4e, 0x16, 0x27, 0x12, 0x99, 0x95, 0x62, 0xe6, 0x37, 0x18, 0x46, 0xce, + 0x84, 0x2c, 0x56, 0xbe, 0xd1, 0x36, 0x39, 0xff, 0xaa, 0x8d, 0x4a, 0xa6, 0xb4, 0x42, 0x83, 0x67, + 0xb0, 0xc6, 0xdc, 0xe2, 0x08, 0xf1, 0x54, 0x4a, 0x81, 0xf1, 0x07, 0x8a, 0x35, 0xf9, 0xcc, 0x8e, + 0x26, 0xfc, 0x7f, 0xdd, 0x95, 0x42, 0x97, 0x92, 0xdc, 0xf1, 0x80, 0x3a, 0x62, 0x72, 0xc8, 0x69, + 0x1d, 0x61, 0x7f, 0x44, 0xe7, 0x45, 0x71, 0x58, 0xd8, 0x8c, 0xb9, 0x2f, 0xec, 0xe4, 0xc0, 0x03, + 0xe6, 0xc0, 0x86, 0xa0, 0xe2, 0xc8, 0xf1, 0x24, 0x4e, 0xf3, 0xca, 0x2e, 0x49, 0x5a, 0x16, 0x60, + 0x4c, 0xe5, 0xd2, 0x88, 0xd6, 0x16, 0x3b, 0x93, 0x44, 0x14, 0xe9, 0x26, 0xf0, 0x1e, 0x0e, 0x9d, + 0xb1, 0x3f, 0xe7, 0xe3, 0xa3, 0x81, 0x3b, 0x07, 0xe7, 0xe1, 0xdf, 0xd6, 0xe9, 0x86, 0x6f, 0x66, + 0xdc, 0x20, 0xe9, 0x19, 0x07, 0x56, 0xbc, 0x76, 0x91, 0x20, 0x97, 0xc9, 0x7a, 0x70, 0xbd, 0x40, + 0x64, 0x2f, 0xbf, 0x09, 0x33, 0x70, 0x67, 0x49, 0x23, 0x9c, 0x30, 0x1c, 0x28, 0x74, 0x0a, 0xdb, + 0x52, 0x53, 0xf1, 0x31, 0xb8, 0x5e, 0xaa, 0xb0, 0xca, 0x25, 0xda, 0xb2, 0x59, 0x52, 0x75, 0x83, + 0x99, 0xfa, 0x52, 0xd2, 0xf2, 0xeb, 0xaf, 0xc5, 0x1b, 0x94, 0xd6, 0xa3, 0x1c, 0xa0, 0xba, 0x02, + 0xe6, 0x94, 0xa4, 0x85, 0x52, 0x51, 0xb9, 0xeb, 0x09, 0xa4, 0x9b, 0xc3, 0x81, 0xb6, 0xcc, 0x21, + 0x7e, 0x36, 0x78, 0x31, 0x95, 0xa0, 0x9f, 0x4a, 0x96, 0x87, 0x54, 0xef, 0x09, 0x8c, 0x5a, 0x63, + 0xfd, 0x39, 0xa1, 0x18, 0xd5, 0xd4, 0x00, 0x8e, 0x9c, 0xec, 0x4f, 0xe5, 0x1d, 0xf8, 0x23, 0x79, + 0xdf, 0x06, 0x88, 0x5a, 0x96, 0x96, 0x91, 0xe9, 0xed, 0x50, 0xa3, 0x42, 0xad, 0xa8, 0x7c, 0x9a, + 0x29, 0xf2, 0x3c, 0x29, 0xfc, 0xc3, 0xb4, 0x11, 0x06, 0x54, 0x8b, 0x76, 0x20, 0x0a, 0x96, 0x66, + 0x8e, 0xb8, 0xaa, 0x77, 0x2d, 0x24, 0x1a, 0xd8, 0x7c, 0xb0, 0x4c, 0x10, 0x33, 0xdb, 0xb5, 0x2e, + 0x30, 0x77, 0xd3, 0x68, 0x20, 0x90, 0xf5, 0x94, 0xe2, 0xe5, 0xda, 0xe6, 0x04, 0xec, 0x49, 0x80, + 0x30, 0xad, 0x86, 0x4d, 0x83, 0x69, 0x2a, 0x11, 0xe8, 0xb9, 0xd5, 0x92, 0xf0, 0x56, 0xb2, 0x89, + 0x52, 0xf2, 0x9b, 0x13, 0x72, 0x51, 0xfc, 0x1a, 0x84, 0xe6, 0x6a, 0x78, 0x1a, 0x4f, 0x2f, 0xb5, + 0xeb, 0xfb, 0x63, 0x88, 0x68, 0xf2, 0xe9, 0xa3, 0x54, 0x53, 0xec, 0x39, 0xf8, 0x3f, 0x1d, 0x58, + 0xe4, 0x1a, 0x25, 0xd1, 0xb9, 0x27, 0x02, 0x4f, 0x5a, 0xc2, 0x29, 0x07, 0xda, 0xa6, 0x97, 0xc4, + 0x37, 0x52, 0xa2, 0x3a, 0x04, 0x0c, 0xdf, 0x75, 0x1f, 0x2e, 0x7e, 0x2f, 0xca, 0x20, 0x25, 0xe6, + 0xa0, 0x55, 0xc9, 0x86, 0x04, 0xb1, 0xa2, 0x2b, 0xc1, 0xb1, 0xdb, 0xd3, 0xf0, 0x91, 0x87, 0x34, + 0x2a, 0x0c, 0x99, 0xcb, 0x5a, 0xd5, 0x27, 0xa6, 0x4d, 0xda, 0xda, 0xbf, 0x6a, 0x93, 0x3a, 0x90, + 0x03, 0x8d, 0x8c, 0xd6, 0xb2, 0xad, 0x6a, 0x8d, 0x9a, 0xb9, 0x01, 0x05, 0xcd, 0x9f, 0x62, 0x90, + 0x86, 0x26, 0xaf, 0xf5, 0x37, 0xc0, 0x8a, 0x8b, 0x57, 0x31, 0x71, 0x9d, 0x01, 0x0e, 0x2d, 0xa0, + 0x19, 0xeb, 0xb1, 0x67, 0x03, 0xae, 0xa7, 0x08, 0x06, 0x7a, 0x80, 0xa0, 0x5d, 0x07, 0x17, 0x63, + 0x2b, 0xe7, 0x45, 0x9e, 0xa5, 0x76, 0xb7, 0xb1, 0x8a, 0x55, 0x4b, 0xaf, 0x21, 0x4e, 0xfd, 0xfa, + 0x2d, 0xf5, 0x9d, 0x57, 0xf3, 0x39, 0xce, 0x44, 0xac, 0x8a, 0x6c, 0xbd, 0xbd, 0x91, 0x8b, 0xae, + 0xa9, 0x7a, 0x18, 0x73, 0xf2, 0x12, 0xc0, 0x5f, 0x85, 0x5b, 0x23, 0xa5, 0x76, 0x98, 0xd9, 0x0a, + 0x39, 0xa8, 0x28, 0xbb, 0x91, 0x7b, 0x61, 0x7a, 0xa1, 0xd0, 0xfe, 0x39, 0xa9, 0x42, 0x9b, 0xb7, + 0x5f, 0x36, 0x91, 0xaa, 0x6e, 0x15, 0xb4, 0x0c, 0x2c, 0xa2, 0x5a, 0x4e, 0x09, 0xe8, 0xf2, 0x1b, + 0x18, 0xe8, 0xa6, 0x3b, 0x1c, 0x41, 0xb5, 0xb3, 0xe8, 0xc0, 0xe7, 0xba, 0x5d, 0x32, 0xaf, 0x15, + 0x2c, 0x25, 0x7f, 0x13, 0xe5, 0x05, 0xcc, 0xd9, 0xc1, 0x8d, 0xa1, 0x01, 0xf3, 0x0a, 0x81, 0x1f, + 0x9b, 0xa3, 0xdf, 0x41, 0xb4, 0x31, 0x9c, 0x00, 0xd1, 0x98, 0x4b, 0x10, 0x6d, 0x89, 0xc7, 0x89, + 0xa5, 0xda, 0x8b, 0x70, 0xb6, 0xe9, 0xf0, 0x07, 0x51, 0xd1, 0xa4, 0x7f, 0x54, 0xcd, 0xa7, 0x64, + 0xf5, 0xe3, 0x5f, 0x51, 0x83, 0x8c, 0x58, 0xb3, 0xa4, 0x54, 0x7f, 0x80, 0x62, 0x2a, 0x8b, 0xb8, + 0x5b, 0x33, 0x12, 0x31, 0x49, 0x8f, 0x16, 0x89, 0x70, 0xdb, 0x74, 0x91, 0x08, 0xeb, 0x84, 0xd1, + 0x83, 0xa3, 0x17, 0x46, 0x09, 0xc2, 0x0c, 0x92, 0x93, 0x1c, 0xa8, 0xc7, 0x0f, 0xf7, 0xf2, 0xfb, + 0x12, 0x51, 0xf7, 0x0d, 0x66, 0xad, 0x2e, 0xfb, 0xed, 0xe9, 0x61, 0xa8, 0x73, 0xef, 0xe0, 0x78, + 0x59, 0xfb, 0x56, 0x89, 0x9a, 0x9c, 0x82, 0x8f, 0x90, 0xe7, 0x3e, 0x11, 0x7f, 0x0d, 0x1f, 0xea, + 0x08, 0xfc, 0x48, 0x5c, 0xfc, 0x6a, 0xe5, 0x9d, 0x67, 0xa4, 0x69, 0x12, 0xdd, 0xc8, 0xa1, 0xbe, + 0x1e, 0x27, 0xda, 0xec, 0x50, 0xa3, 0x21, 0xf6, 0xca, 0x8c, 0x2e, 0x64, 0x0b, 0xa1, 0x85, 0xe2, + 0x0f, 0xb9, 0x39, 0x32, 0xf9, 0x62, 0x73, 0x3e, 0x04, 0xea, 0xb2, 0x35, 0xfc, 0x3a, 0x86, 0xe7, + 0x44, 0x92, 0x84, 0xa2, 0x59, 0x07, 0xec, 0x52, 0x36, 0x29, 0xad, 0x69, 0x41, 0xb1, 0x7b, 0xdd, + 0x39, 0x61, 0x19, 0x51, 0xef, 0xad, 0x63, 0xff, 0x33, 0x2d, 0xae, 0x00, 0xa6, 0x0e, 0x44, 0x8f, + 0x6b, 0x79, 0x01, 0xd9, 0x61, 0xfd, 0xdb, 0xb5, 0x9c, 0xba, 0x28, 0x7b, 0x88, 0x9c, 0x0f, 0x63, + 0xa6, 0xfb, 0x6a, 0x74, 0x28, 0x29, 0xaf, 0x02, 0x12, 0xc4, 0x69, 0xdf, 0x69, 0x33, 0x74, 0xe4, + 0x59, 0xab, 0x91, 0x56, 0x4b, 0x95, 0x4e, 0xc7, 0x49, 0x00, 0x42, 0x4e, 0xc1, 0xb6, 0x89, 0xba, + 0x83, 0x59, 0x83, 0x7e, 0x21, 0xc4, 0x85, 0xbe, 0xf0, 0xbe, 0x7c, 0x75, 0x89, 0xef, 0xf5, 0xd7, + 0x95, 0x62, 0xe7, 0xeb, 0xc3, 0xfc, 0x28, 0xc3, 0xea, 0x23, 0x5b, 0xe2, 0x4f, 0xb6, 0xca, 0x40, + 0xf5, 0x7f, 0x08, 0x85, 0x96, 0x91, 0xba, 0x74, 0xb5, 0x0c, 0xf4, 0x6b, 0x2b, 0x6e, 0x2e, 0x54, + 0x36, 0x89, 0xb2, 0x83, 0x7e, 0xc4, 0xf4, 0xee, 0x86, 0x4c, 0xfa, 0xea, 0x4a, 0x51, 0x54, 0x56, + 0x03, 0xd4, 0x9c, 0x63, 0x99, 0xb9, 0x76, 0x89, 0x34, 0x24, 0x57, 0x4d, 0x74, 0x8d, 0xc5, 0xa7, + 0x0b, 0xcd, 0xaf, 0x2c, 0x92, 0x57, 0x98, 0x26, 0x2b, 0x07, 0x47, 0x6d, 0xdf, 0x11, 0xde, 0xad, + 0x73, 0xce, 0x87, 0xdf, 0x22, 0x28, 0x1f, 0x5b, 0x60, 0xf9, 0xf1, 0xd9, 0xbb, 0xac, 0xf2, 0x14, + 0xcd, 0x5d, 0x29, 0xe2, 0x0d, 0xd6, 0x7c, 0x20, 0xfe, 0x09, 0x15, 0x36, 0x78, 0x80, 0xf6, 0x8c, + 0x33, 0x0f, 0x11, 0xad, 0xb6, 0x63, 0x5f, 0xba, 0xf1, 0xfc, 0x74, 0x40, 0xc9, 0x55, 0xbb, 0xce, + 0x18, 0xcd, 0xce, 0x05, 0x04, 0x19, 0x0b, 0x21, 0x64, 0x75, 0xf0, 0x64, 0x1b, 0x73, 0xc2, 0xf3, + 0xc8, 0xa9, 0x1b, 0x50, 0x93, 0xa5, 0x02, 0x57, 0x4b, 0xcc, 0xf1, 0x48, 0x11, 0x48, 0xe2, 0x00, + 0x04, 0xff, 0x73, 0x9e, 0x56, 0xe7, 0xb7, 0xc2, 0xa9, 0x34, 0x52, 0x3d, 0xd8, 0x2a, 0xfa, 0x8d, + 0x68, 0x87, 0x79, 0xdd, 0x9a, 0xfd, 0x02, 0xc3, 0x78, 0xe7, 0x41, 0x0b, 0x50, 0x60, 0x41, 0x39, + 0xc3, 0x0e, 0xa8, 0x73, 0x3d, 0x9d, 0x16, 0xba, 0xb7, 0x0a, 0x07, 0xc9, 0x6a, 0x3c, 0xd1, 0x24, + 0x62, 0x57, 0x2a, 0x58, 0xce, 0x11, 0x69, 0xe0, 0xc0, 0x51, 0x29, 0x20, 0xb6, 0x8e, 0xf5, 0x24, + 0xd9, 0x8c, 0x85, 0x40, 0x2e, 0xc6, 0x24, 0xd6, 0x91, 0x1d, 0xd2, 0x3e, 0x6c, 0x50, 0x7b, 0x69, +}; + +// our replacement pub/privkeys +const unsigned char our_pubkey[140] = { + 0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00, 0xbb, 0xed, 0xa6, 0x26, 0xec, 0xe7, 0xc3, 0x60, 0x07, + 0xe7, 0xab, 0xf4, 0x05, 0x2f, 0xde, 0x6b, 0x86, 0x92, 0x65, 0x57, 0xf8, 0x57, 0xf5, 0xb2, 0x8f, + 0xe1, 0x2b, 0x4f, 0x73, 0xb1, 0x4a, 0xf1, 0xf2, 0xcc, 0x7f, 0x49, 0xd1, 0xd2, 0x48, 0xf1, 0x29, + 0x73, 0x59, 0x5c, 0x5d, 0x4a, 0x4f, 0x0f, 0x29, 0x15, 0xa8, 0xea, 0x7c, 0x92, 0x59, 0xa9, 0x8a, + 0x64, 0x5f, 0xba, 0x5a, 0x40, 0x43, 0x1f, 0x2d, 0x63, 0x5a, 0xd9, 0x31, 0x60, 0xd5, 0xa2, 0xac, + 0x99, 0xa1, 0xc9, 0x40, 0xf8, 0x92, 0xe5, 0x12, 0xe7, 0xa4, 0xeb, 0xe6, 0x02, 0xb3, 0xef, 0x5c, + 0xa4, 0x7f, 0x8f, 0x7f, 0xc8, 0x6f, 0xbe, 0x48, 0xaf, 0x0b, 0x67, 0x87, 0xd6, 0x73, 0xd3, 0xe8, + 0xba, 0x1f, 0x01, 0xfe, 0x9f, 0x35, 0xfd, 0xc1, 0x38, 0x7d, 0x39, 0x10, 0xed, 0x07, 0x77, 0x02, + 0xca, 0xf3, 0x52, 0xec, 0x7b, 0x1c, 0x83, 0x02, 0x03, 0x01, 0x00, 0x01 +}; + +// ppro official pubkey +const unsigned char their_pubkey[140] = { + 0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00, 0xb7, 0x0d, 0x2c, 0xe1, 0xf3, 0xaf, 0x2b, 0xec, 0xfb, + 0xe3, 0x00, 0x75, 0x42, 0xbf, 0x9b, 0xf5, 0x85, 0x9f, 0xf0, 0x8f, 0x2c, 0x36, 0x2a, 0xb6, 0x7c, + 0x81, 0x78, 0x3d, 0x05, 0x7f, 0xc6, 0xec, 0xd3, 0x34, 0xed, 0x31, 0x73, 0x0b, 0xa4, 0x81, 0x25, + 0xa8, 0xe2, 0x0f, 0x02, 0xce, 0xba, 0x82, 0x95, 0xb9, 0x5a, 0x49, 0xc7, 0xe6, 0x6e, 0xb3, 0xe2, + 0xcc, 0xae, 0x18, 0x7f, 0x0f, 0xde, 0x5f, 0x03, 0x06, 0x00, 0x3d, 0xa5, 0x15, 0x6d, 0x7e, 0x0e, + 0x8a, 0x8b, 0xbf, 0x26, 0x26, 0xee, 0x2a, 0xd8, 0x45, 0xdc, 0xd2, 0xba, 0xf0, 0x44, 0x13, 0x6e, + 0xc6, 0xc3, 0x79, 0x57, 0xfc, 0x14, 0x32, 0x01, 0x95, 0x66, 0xe5, 0x34, 0x9c, 0xc6, 0x49, 0xf3, + 0xb0, 0x81, 0x6e, 0x26, 0x64, 0xa9, 0x9d, 0x04, 0xa2, 0x44, 0x3a, 0xde, 0x3b, 0x5e, 0xa4, 0x6e, + 0xfd, 0x28, 0x01, 0xd2, 0xd9, 0x61, 0x45, 0x02, 0x03, 0x01, 0x00, 0x01, +}; + +void usage(const char *prog) { + fprintf(stderr, "Usage: %s [-p] \n", prog); + fprintf(stderr, "\nVerifies zip files\n"); + fprintf(stderr, "-p\t\tuse official keypair for verification\n"); +} + +int main(int argc, char *argv[]) { + rsa_key ourkey; + int err; + int verified = 0; + unsigned char hash1[20], hash2[20]; + unsigned long amt; + int sha1_idx; + hash_state md, md2; + char srsly[6]; + int opt; + int use_official_keypair = 0; + int has_sig = 0; + + memset(srsly, 0, sizeof(srsly)); + ltc_mp = ltm_desc; + + while ((opt = getopt(argc, argv, "p")) != -1) { + switch (opt) { + case 'p': + use_official_keypair = 1; + break; + default: + usage(argv[0]); + return 2; + } + } + if (optind >= argc) { + usage(argv[0]); + return 2; + } + + if ((sha1_idx = register_hash(&sha1_desc)) == -1) { + fprintf(stderr, "Could not register SHA1 hash descriptor\n"); + return -1; + } + + sha1_init(&md); + sha1_init(&md2); + + const unsigned char *keypair = use_official_keypair ? their_pubkey : our_pubkey; + if ((err = rsa_import(keypair, sizeof(our_pubkey), &ourkey)) != CRYPT_OK) { + fprintf(stderr, "rsa_import: %s\n", error_to_string(err)); + return 1; + } + + FILE *zip_fd = fopen(argv[optind], "rb"); + if (zip_fd == NULL) { + perror("fopen(zip_fd)"); + return 1; + } + fseek(zip_fd, -5, SEEK_END); + if (fread(srsly, 1, 5, zip_fd) != 5) { + perror("fread(srsly)"); + return 1; + } + + // if "SRSLY" is at the very end of the file, the 128 bytes before + // it is an attached signature. Otherwise, verify with the hardcoded + // signatures + fseek(zip_fd, 0, SEEK_END); + if (strcmp(srsly, "SRSLY") == 0) { + has_sig = 1; + printf("%s has attached signature\n", argv[optind]); + amt = ftell(zip_fd) - 133; + } else { + amt = ftell(zip_fd); + } + + printf("%s: reading %lu bytes...\n", argv[optind], amt); + + unsigned char buf[0x10000], sig[128]; + size_t got = 0, readsize = 0; + off_t pos = 0; + long curpos = 0; + + while (pos < amt) { + fseek(zip_fd, pos, SEEK_SET); + curpos = ftell(zip_fd); + readsize = (amt < 0x10000) ? amt : 0x10000; + got = fread(buf, 1, readsize, zip_fd); + if (got != readsize) { + perror("fread(zip_fd)"); + fclose(zip_fd); + return 1; + } + sha1_process(&md, buf, got); + printf("processed %d bytes at %lu\n", got, curpos); + if (pos + got >= amt) { + break; + } + pos += 0x1000000; + if (pos + 0x10000 > amt) { + pos = amt - 0x10000; + } + } + + if ((has_sig) && (fread(sig, 1, sizeof(sig), zip_fd) != sizeof(sig))) { + fprintf(stderr, "fread(sig): %s\n", strerror(errno)); + fclose(zip_fd); + return 1; + } + fclose(zip_fd); + + sha1_done(&md, hash1); + sha1_process(&md2, hash1, 20); + sha1_done(&md2, hash2); + + /* + * patch.zip: + * + * 1st iter: + * (gdb) x/20cx $ebp + * 0xfffece60: 0x1f 0x5f 0xd9 0xcb 0xec 0xaa 0xac 0x08 + * 0xfffece68: 0x0b 0x90 0xb8 0x8c 0xc9 0x34 0xb0 0x03 + * 0xfffece70: 0xbc 0xaf 0xa5 0xeb + * + * 2nd iter: + * (gdb) x/20cx $esi + * 0xfffece00: 0x41 0x39 0xe9 0xd1 0xb9 0x18 0xd0 0xe8 + * 0xfffece08: 0x5a 0xd4 0xc6 0x6d 0xad 0x3c 0x9d 0x07 + * 0xfffece10: 0xdf 0xe0 0xa6 0xd0 + * */ + printf("hash1: "); + for (int i = 0; i < 20; i++) { + printf("%02x", hash1[i]); + } + printf("\n"); + printf("hash2: "); + for (int i = 0; i < 20; i++) { + printf("%02x", hash2[i]); + } + printf("\n"); + + // XXX + printf("poc: "); + hash_state blah; + sha1_init(&blah); + // patch.zip official hash1 + unsigned char stuff[20] = {0x1f, 0x5f, 0xd9, 0xcb, 0xec, 0xaa, 0xac, 0x08, 0x0b, 0x90, 0xb8, 0x8c, 0xc9, 0x34, 0xb0, 0x03, 0xbc, 0xaf, 0xa5, 0xeb}; + unsigned char realdeal[20]; + sha1_process(&blah, stuff, sizeof(stuff)); + sha1_done(&blah, realdeal); + for (int i = 0; i < 20; i++) { + printf("%02x", realdeal[i]); + } + printf("\n"); + + if (has_sig) { + printf("sig start: %02x %02x %02x %02x %02x %02x\n", sig[0], sig[1], sig[2], sig[3], sig[4], sig[5]); + if ((err = rsa_verify_hash_ex(sig, 128, hash2, sizeof(hash2), LTC_PKCS_1_V1_5, sha1_idx, 0, &verified, &ourkey)) != CRYPT_OK) { + if (err != CRYPT_INVALID_PACKET) { + // libtomcrypt will return CRYPT_INVALID_PACKET + // if the pubkey fails to decode the sig to begin + // with + fprintf(stderr, "rsa_verify_hash_ex: (%d) %s\n", err, error_to_string(err)); + return 1; + } + verified = 0; + } + + printf("verified: %d\n", verified); + } else { + int sig_index = 0; + for (; sig_index < 67; sig_index++) { + if ((err = rsa_verify_hash_ex(official_sig_data+(sig_index*128), 128, hash2, sizeof(hash2), LTC_PKCS_1_V1_5, sha1_idx, 0, &verified, &ourkey)) != CRYPT_OK) { + if (err == CRYPT_INVALID_PACKET) { + // libtomcrypt will return CRYPT_INVALID_PACKET + // if the pubkey fails to decode the sig to begin + // with + continue; + } + fprintf(stderr, "rsa_verify_hash_ex: (%d) %s\n", err, error_to_string(err)); + return 1; + } + if (verified) { + break; + } + } + + printf("verified: %d (%d)\n", verified, sig_index); + } + + return 0; +} diff --git a/src/plugins/pro1_data_zip/util.c b/src/plugins/pro1_data_zip/util.c new file mode 100644 index 0000000..6e14922 --- /dev/null +++ b/src/plugins/pro1_data_zip/util.c @@ -0,0 +1,10 @@ +#include +#include +#include +#include "util.h" + +void generate_random_bytes(uint8_t *buf, int count) { + for (int i = 0; i < count; i++) { + buf[i] = rand() % 255; + } +} diff --git a/src/plugins/pro1_data_zip/util.h b/src/plugins/pro1_data_zip/util.h new file mode 100644 index 0000000..4a252ab --- /dev/null +++ b/src/plugins/pro1_data_zip/util.h @@ -0,0 +1,6 @@ +#pragma once +#include + +#define min(x,y) ((x) > (y) ? (y) : (x)) + +void generate_random_bytes(uint8_t *buf, int count);