diff --git a/dap-sdk/core/CMakeLists.txt b/dap-sdk/core/CMakeLists.txt index 31c0eea678deae9981cbe572f79b2145150b5bc3..c7d865b88b1e14f2e06fc7a0e61a20353338904e 100755 --- a/dap-sdk/core/CMakeLists.txt +++ b/dap-sdk/core/CMakeLists.txt @@ -100,7 +100,7 @@ endif() if(ANDROID) add_subdirectory(src/android) - target_link_libraries(${PROJECT_NAME} dap_core_android) + target_link_libraries(${PROJECT_NAME} dap_core_android rt) endif() if (WIN32) diff --git a/dap-sdk/core/include/dap_strfuncs.h b/dap-sdk/core/include/dap_strfuncs.h index ea2f6c20bc7b6566b4158121402b3ea414c9a352..c581294cb9df00d18df510e4425c3e4f8787414e 100755 --- a/dap-sdk/core/include/dap_strfuncs.h +++ b/dap-sdk/core/include/dap_strfuncs.h @@ -108,7 +108,7 @@ char *dap_itoa128(char *a_str, int128_t a_value, int a_base); #ifdef HAVE_STRNDUP #define strndup(s, l) _strndup(s, l) #endif -char *_strndup(char *str, unsigned long len); +char *_strndup(const char *str, unsigned long len); #endif #define DAP_USEC_PER_SEC 1000000 diff --git a/dap-sdk/core/src/dap_common.c b/dap-sdk/core/src/dap_common.c index c2c8cf55f7108cf6e177d04c244346745897f06a..3803cfee430abe230ac629a1da667c775695e799 100755 --- a/dap-sdk/core/src/dap_common.c +++ b/dap-sdk/core/src/dap_common.c @@ -827,7 +827,7 @@ static int s_timer_find(void *a_timer) static void CALLBACK s_win_callback(PVOID a_arg, BOOLEAN a_always_true) { UNUSED(a_always_true); - s_timers[(int)a_arg].callback(s_timers[(int)a_arg].param); + s_timers[(size_t)a_arg].callback(s_timers[(size_t)a_arg].param); } #elif defined __MACH__ static void s_bsd_callback(int a_arg) @@ -852,12 +852,12 @@ void *dap_interval_timer_create(unsigned int a_msec, dap_timer_callback_t a_call if (s_timers_count == DAP_INTERVAL_TIMERS_MAX) { return NULL; } -#ifdef _WIN32 +#ifdef WIN32 if (s_timers_count == 0) { InitializeCriticalSection(&s_timers_lock); } HANDLE l_timer; - if (!CreateTimerQueueTimer(&l_timer, NULL, (WAITORTIMERCALLBACK)s_win_callback, (PVOID)s_timers_count, a_msec, a_msec, 0)) { + if (!CreateTimerQueueTimer(&l_timer, NULL, (WAITORTIMERCALLBACK)s_win_callback, (PVOID)(size_t)s_timers_count, a_msec, a_msec, 0)) { return NULL; } EnterCriticalSection(&s_timers_lock); @@ -888,6 +888,8 @@ void *dap_interval_timer_create(unsigned int a_msec, dap_timer_callback_t a_call l_period.it_interval.tv_nsec = l_period.it_value.tv_nsec = (a_msec % 1000) * 1000000; timer_settime(l_timer, 0, &l_period, NULL); pthread_mutex_lock(&s_timers_lock); +#else + //DARWIN #endif s_timers[s_timers_count].timer = (void *)l_timer; s_timers[s_timers_count].callback = a_callback; @@ -895,8 +897,10 @@ void *dap_interval_timer_create(unsigned int a_msec, dap_timer_callback_t a_call s_timers_count++; #ifdef _WIN32 LeaveCriticalSection(&s_timers_lock); -#else +#elif DAP_OS_UNIX pthread_mutex_unlock(&s_timers_lock); +#else + //DARWIN #endif return (void *)l_timer; } @@ -913,8 +917,10 @@ int dap_interval_timer_delete(void *a_timer) } #ifdef _WIN32 EnterCriticalSection(&s_timers_lock); -#else +#elif DAP_OS_UNIX pthread_mutex_lock(&s_timers_lock); +#else + //DARWIN #endif int l_timer_idx = s_timer_find(a_timer); if (l_timer_idx == -1) { @@ -930,7 +936,8 @@ int dap_interval_timer_delete(void *a_timer) DeleteCriticalSection(&s_timers_lock); } return !DeleteTimerQueueTimer(NULL, (HANDLE)a_timer, NULL); -#else +#elif DAP_OS_UNIX + pthread_mutex_unlock(&s_timers_lock); if (s_timers_count == 0) { pthread_mutex_destroy(&s_timers_lock); } @@ -939,6 +946,8 @@ int dap_interval_timer_delete(void *a_timer) return 0; #else return timer_delete((timer_t)a_timer); +#else + //DARWIN #endif #endif } diff --git a/dap-sdk/core/src/dap_strfuncs.c b/dap-sdk/core/src/dap_strfuncs.c index 99180b36fc207d2a3d345a69d344d711815dc6e1..2685947f96e330bdc41bb865cfac7434e6e2d326 100755 --- a/dap-sdk/core/src/dap_strfuncs.c +++ b/dap-sdk/core/src/dap_strfuncs.c @@ -855,7 +855,7 @@ char *strptime( char *buff, const char *fmt, struct tm *tm ) { return buff + len; } -char *_strndup(char *str, unsigned long len) { +char *_strndup(const char *str, unsigned long len) { char *buf = (char*)memchr(str, '\0', len); if (buf) len = buf - str; diff --git a/dap-sdk/crypto/CMakeLists.txt b/dap-sdk/crypto/CMakeLists.txt index 51423bd00b470a69dadef7c609044279744e2b42..0d5a8a979c32373f627da157cae3e8ade9afa8ff 100755 --- a/dap-sdk/crypto/CMakeLists.txt +++ b/dap-sdk/crypto/CMakeLists.txt @@ -92,7 +92,7 @@ endif() add_library(${PROJECT_NAME} STATIC ${CRYPTO_SRCS} ${XKCP_SRCS} ${XKCP_SRCS2} ${CRYPTO_HEADERS} ) -target_include_directories(dap_crypto PRIVATE src/rand src/iaes src/oaes src/sha3 src/msrln src/defeo_scheme src/sig_bliss src/sig_tesla src/sig_picnic src/sig_dilithium src include) +target_include_directories(dap_crypto PRIVATE src/seed src/rand src/iaes src/oaes src/sha3 src/msrln src/defeo_scheme src/sig_bliss src/sig_tesla src/sig_picnic src/sig_dilithium src include) target_include_directories(dap_crypto INTERFACE src/ src/sha3 include/) target_include_directories(dap_crypto PUBLIC diff --git a/dap-sdk/crypto/src/GOST/28147_14.c b/dap-sdk/crypto/src/GOST/28147_14.c index 69133fa7771e4083c7b526f2b06627af4723660d..7b49540a848f09aeacb7d0cbe04236c429b9fd2c 100644 --- a/dap-sdk/crypto/src/GOST/28147_14.c +++ b/dap-sdk/crypto/src/GOST/28147_14.c @@ -403,7 +403,7 @@ int DLL_IMPORT ExpandKey(unsigned char* masterKey, unsigned char* keys, printou return 0; } -int DLL_IMPORT Encrypt_14(unsigned char* plainText, unsigned char* chipherText, unsigned char* keys, printout_byte_array print, printout_uint_array print_uint) +int DLL_IMPORT Encrypt_14(const unsigned char* plainText, unsigned char* chipherText, unsigned char* keys, printout_byte_array print, printout_uint_array print_uint) { unsigned char xTemp[16]; unsigned char yTemp[16]; @@ -442,7 +442,7 @@ int DLL_IMPORT Encrypt_14(unsigned char* plainText, unsigned char* chipherText, return 0; } -int DLL_IMPORT Decrypt_14(unsigned char* chipherText, unsigned char* plainText, unsigned char* keys, printout_byte_array print, printout_uint_array print_uint) +int DLL_IMPORT Decrypt_14(const unsigned char* chipherText, unsigned char* plainText, unsigned char* keys, printout_byte_array print, printout_uint_array print_uint) { unsigned char xTemp[16]; unsigned char yTemp[16]; @@ -478,4 +478,4 @@ int DLL_IMPORT Decrypt_14(unsigned char* chipherText, unsigned char* plainText, } return 0; -} \ No newline at end of file +} diff --git a/dap-sdk/crypto/src/GOST/28147_14.h b/dap-sdk/crypto/src/GOST/28147_14.h index 80ac954416dea6970a459373d8d61e691f94512d..2bc201a9d42e8da24a29076197b3da02d10d402d 100644 --- a/dap-sdk/crypto/src/GOST/28147_14.h +++ b/dap-sdk/crypto/src/GOST/28147_14.h @@ -151,7 +151,7 @@ int DLL_IMPORT ExpandKey(unsigned char* masterKey, unsigned char* keys, printout * @return 0 еÑли вÑе преобразование прошло уÑпешно * @return -1 еÑли произошла ошибка */ -int DLL_IMPORT Encrypt_14(unsigned char* plainText, unsigned char* chipherText, unsigned char* keys, printout_byte_array print, printout_uint_array print_uint); +int DLL_IMPORT Encrypt_14(const unsigned char* plainText, unsigned char* chipherText, unsigned char* keys, printout_byte_array print, printout_uint_array print_uint); /** @brief Выполение раÑÑˆÐ¸Ñ„Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ð±Ð»Ð¾ÐºÐ° * @@ -163,7 +163,7 @@ int DLL_IMPORT Encrypt_14(unsigned char* plainText, unsigned char* chipherText, * @return 0 еÑли вÑе преобразование прошло уÑпешно * @return -1 еÑли произошла ошибка */ -int DLL_IMPORT Decrypt_14(unsigned char* chipherText, unsigned char* plainText, unsigned char* keys, printout_byte_array print, printout_uint_array print_uint); +int DLL_IMPORT Decrypt_14(const unsigned char* chipherText, unsigned char* plainText, unsigned char* keys, printout_byte_array print, printout_uint_array print_uint); #ifdef __cplusplus } diff --git a/dap-sdk/crypto/src/GOST/28147_89.c b/dap-sdk/crypto/src/GOST/28147_89.c index 0f45378cac7b356a8b8247a52407aec8705ea979..60eda929366dc55ebc41eea0d290883e7685c40b 100644 --- a/dap-sdk/crypto/src/GOST/28147_89.c +++ b/dap-sdk/crypto/src/GOST/28147_89.c @@ -11,7 +11,7 @@ * @param[in] input маÑÑив из 4 байт * @return int32 чиÑло */ -static unsigned int uint8ToUint32(unsigned char* input) +static unsigned int uint8ToUint32(const unsigned char* input) { unsigned int r = ( (input[3]) | (input[2]<<8) | (input[1]<<16) | (input[0]<<24)); return r; @@ -143,7 +143,7 @@ void DLL_IMPORT RoundShtrih(unsigned int* a1, unsigned int* a0, unsigned int k, } } -int DLL_IMPORT CryptBlock(unsigned char* input, unsigned char* output, unsigned char* key, unsigned char* keyIndex, printout_uint_array print) +int DLL_IMPORT CryptBlock(const unsigned char* input, unsigned char* output, unsigned char* key, unsigned char* keyIndex, printout_uint_array print) { unsigned int a1 = uint8ToUint32(input); unsigned int a0 = uint8ToUint32(input + 4); @@ -175,17 +175,17 @@ int DLL_IMPORT CryptBlock(unsigned char* input, unsigned char* output, unsigned return 0; } -int DLL_IMPORT EncryptBlock(unsigned char* input, unsigned char* output, unsigned char* key, printout_uint_array print) +int DLL_IMPORT EncryptBlock(const unsigned char* input, unsigned char* output, unsigned char* key, printout_uint_array print) { return CryptBlock(input, output, key, kEncRoundKey, print); } -int DLL_IMPORT DecryptBlock(unsigned char* input, unsigned char* output, unsigned char* key, printout_uint_array print) +int DLL_IMPORT DecryptBlock(const unsigned char* input, unsigned char* output, unsigned char* key, printout_uint_array print) { return CryptBlock(input, output, key, kDecRoundKey, print); } -int DLL_IMPORT Encrypt_89(unsigned char* input, unsigned char* output, unsigned char* key, printout_byte_array print, printout_uint_array print_uint) +int DLL_IMPORT Encrypt_89(const unsigned char* input, unsigned char* output, unsigned char* key, printout_byte_array print, printout_uint_array print_uint) { if( !input || !output || !key ) { @@ -206,7 +206,7 @@ int DLL_IMPORT Encrypt_89(unsigned char* input, unsigned char* output, unsigned return 0; } -int DLL_IMPORT Decrypt_89(unsigned char* input, unsigned char* output, unsigned char* key, printout_byte_array print, printout_uint_array print_uint) +int DLL_IMPORT Decrypt_89(const unsigned char* input, unsigned char* output, unsigned char* key, printout_byte_array print, printout_uint_array print_uint) { if( !input || !output || !key ) { diff --git a/dap-sdk/crypto/src/GOST/28147_89.h b/dap-sdk/crypto/src/GOST/28147_89.h index a0f78eb8a7ae1be046866357be601aafddd1c2e0..5a80f03a45c4f0553dfa2f5fb6f8a61443f90b41 100644 --- a/dap-sdk/crypto/src/GOST/28147_89.h +++ b/dap-sdk/crypto/src/GOST/28147_89.h @@ -59,7 +59,7 @@ void DLL_IMPORT RoundShtrih(unsigned int *a1, unsigned int *a0, unsigned int k, * @return 0 еÑли вÑе преобразование прошло уÑпешно * @return -1 еÑли произошла ошибка */ -int DLL_IMPORT CryptBlock(unsigned char* input, unsigned char* output, unsigned char* key, unsigned char* keySequence, printout_uint_array print); +int DLL_IMPORT CryptBlock(const unsigned char* input, unsigned char* output, unsigned char* key, unsigned char* keySequence, printout_uint_array print); /** @brief Шифруем блок данных * @@ -70,7 +70,7 @@ int DLL_IMPORT CryptBlock(unsigned char* input, unsigned char* output, unsigned * @return 0 еÑли вÑе преобразование прошло уÑпешно * @return -1 еÑли произошла ошибка */ -int DLL_IMPORT EncryptBlock(unsigned char* input, unsigned char* output, unsigned char* key, printout_uint_array print); +int DLL_IMPORT EncryptBlock(const unsigned char* input, unsigned char* output, unsigned char* key, printout_uint_array print); /** @brief РаÑшифровываем блок данных * @@ -81,7 +81,7 @@ int DLL_IMPORT EncryptBlock(unsigned char* input, unsigned char* output, unsigne * @return 0 еÑли вÑе преобразование прошло уÑпешно * @return -1 еÑли произошла ошибка */ -int DLL_IMPORT DecryptBlock(unsigned char* input, unsigned char* output, unsigned char* key, printout_uint_array print); +int DLL_IMPORT DecryptBlock(const unsigned char* input, unsigned char* output, unsigned char* key, printout_uint_array print); /** @brief Шифруем блок данных * @@ -93,7 +93,7 @@ int DLL_IMPORT DecryptBlock(unsigned char* input, unsigned char* output, unsigne * @return 0 еÑли вÑе преобразование прошло уÑпешно * @return -1 еÑли произошла ошибка */ -int DLL_IMPORT Encrypt_89(unsigned char* input, unsigned char* output, unsigned char* key, printout_byte_array print, printout_uint_array print_uint); +int DLL_IMPORT Encrypt_89(const unsigned char* input, unsigned char* output, unsigned char* key, printout_byte_array print, printout_uint_array print_uint); /** @brief РаÑшифровываем блок данных * @@ -105,7 +105,7 @@ int DLL_IMPORT Encrypt_89(unsigned char* input, unsigned char* output, unsigned * @return 0 еÑли вÑе преобразование прошло уÑпешно * @return -1 еÑли произошла ошибка */ -int DLL_IMPORT Decrypt_89(unsigned char* input, unsigned char* output, unsigned char* key, printout_byte_array print, printout_uint_array print_uint); +int DLL_IMPORT Decrypt_89(const unsigned char* input, unsigned char* output, unsigned char* key, printout_byte_array print, printout_uint_array print_uint); #ifdef __cplusplus } diff --git a/dap-sdk/crypto/src/GOST/GOST.pri b/dap-sdk/crypto/src/GOST/GOST.pri index 176c5281c593784d1dbd5853b8aef35a2d1ba64c..2f44dc32c02c18288edaffcd53567d5c4205326d 100644 --- a/dap-sdk/crypto/src/GOST/GOST.pri +++ b/dap-sdk/crypto/src/GOST/GOST.pri @@ -6,11 +6,9 @@ HEADERS += $$PWD/28147_14.h \ $$PWD/dll_import.h \ $$PWD/print_data.h \ $$PWD/table.h \ - $$PWD/test_data.inc \ $$PWD/block_cipher.h SOURCES += $$PWD/28147_14.c \ $$PWD/28147_89.c \ $$PWD/block_cipher.c \ $$PWD/print_data.c \ - $$PWD/testgost.c diff --git a/dap-sdk/crypto/src/GOST/block_cipher.c b/dap-sdk/crypto/src/GOST/block_cipher.c index e6b9d16fd0a2faed222b152a08edf7b559cf4db2..93175427f0e22cb99207cc8cf1fec9060090b65b 100644 --- a/dap-sdk/crypto/src/GOST/block_cipher.c +++ b/dap-sdk/crypto/src/GOST/block_cipher.c @@ -32,10 +32,10 @@ const unsigned char kAlg14 = 1; const unsigned char kAlg89 = 2; /** @brief указатель на функцию ÑˆÐ¸Ñ„Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ */ -typedef int (DLL_IMPORT *pEncrypt)(unsigned char* plainText, unsigned char* chipherText, unsigned char* keys, printout_byte_array print, printout_uint_array print_uint); +typedef int (DLL_IMPORT *pEncrypt)(const unsigned char* plainText, unsigned char* chipherText, unsigned char* keys, printout_byte_array print, printout_uint_array print_uint); /** @brief указатель на функцию раÑÑˆÐ¸Ñ„Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ */ -typedef int (DLL_IMPORT *pDecrypt)(unsigned char* chipherText, unsigned char* plainText, unsigned char* keys, printout_byte_array print, printout_uint_array print_uint); +typedef int (DLL_IMPORT *pDecrypt)(const unsigned char* chipherText, unsigned char* plainText, unsigned char* keys, printout_byte_array print, printout_uint_array print_uint); /** @brief Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ ÑамотеÑÑ‚Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ñ€ÐµÐ¶Ð¸Ð¼Ð° ECB */ static int SelfTestGost14Ecb(); @@ -260,7 +260,7 @@ void DLL_IMPORT free_ecb(void* ctx) } } -static int init_cbc_14_impl(unsigned char *key, void* ctx, unsigned char *iv, size_t ivLength, printout_byte_array print, printout_uint_array print_uint) +static int init_cbc_14_impl(unsigned char *key, void* ctx, const unsigned char *iv, size_t ivLength, printout_byte_array print, printout_uint_array print_uint) { Context_cbc* context; INFOTECS_ASSERT(sizeof(Context_cbc)<=kCbc14ContextLen); @@ -297,14 +297,14 @@ static int init_cbc_14_impl(unsigned char *key, void* ctx, unsigned char *iv, si return 0; } -int DLL_IMPORT init_cbc_14(unsigned char *key, void* ctx, unsigned char *iv, size_t ivLength, printout_byte_array print, printout_uint_array print_uint) +int DLL_IMPORT init_cbc_14(unsigned char *key, void* ctx, const unsigned char *iv, size_t ivLength, printout_byte_array print, printout_uint_array print_uint) { if(SelfTestGost14Cbc()) return -1; return init_cbc_14_impl(key, ctx, iv, ivLength, print, print_uint); } -static int init_cbc_89_impl(unsigned char *key, void* ctx, unsigned char *iv, size_t ivLength, printout_byte_array print, printout_uint_array print_uint) +static int init_cbc_89_impl(unsigned char *key, void* ctx, const unsigned char *iv, size_t ivLength, printout_byte_array print, printout_uint_array print_uint) { Context_cbc* context; INFOTECS_ASSERT(sizeof(Context_cbc)<=kCbc89ContextLen); @@ -341,7 +341,7 @@ static int init_cbc_89_impl(unsigned char *key, void* ctx, unsigned char *iv, si return 0; } -int DLL_IMPORT init_cbc_89(unsigned char *key, void* ctx, unsigned char *iv, size_t ivLength, printout_byte_array print, printout_uint_array print_uint) +int DLL_IMPORT init_cbc_89(unsigned char *key, void* ctx, const unsigned char *iv, size_t ivLength, printout_byte_array print, printout_uint_array print_uint) { if(SelfTestGost89Cbc()) return -1; @@ -386,7 +386,7 @@ void DLL_IMPORT free_cbc(void* ctx) } } -static int init_ctr_14_impl(unsigned char* key, unsigned char *iv, size_t s, void *ctx, printout_byte_array print, printout_uint_array print_uint) +static int init_ctr_14_impl(unsigned char* key, const unsigned char *iv, size_t s, void *ctx, printout_byte_array print, printout_uint_array print_uint) { Context_ctr* context; INFOTECS_ASSERT(sizeof(Context_ctr)<=kCtr14ContextLen); @@ -422,14 +422,14 @@ static int init_ctr_14_impl(unsigned char* key, unsigned char *iv, size_t s, voi return 0; } -int DLL_IMPORT init_ctr_14(unsigned char* key, unsigned char *iv, size_t s, void *ctx, printout_byte_array print, printout_uint_array print_uint) +int DLL_IMPORT init_ctr_14(unsigned char* key, const unsigned char *iv, size_t s, void *ctx, printout_byte_array print, printout_uint_array print_uint) { if(SelfTestGost14Ctr()) return -1; return init_ctr_14_impl(key, iv, s, ctx, print, print_uint); } -static int init_ctr_89_impl(unsigned char* key, unsigned char *iv, size_t s, void *ctx, printout_byte_array print, printout_uint_array print_uint) +static int init_ctr_89_impl(unsigned char* key, const unsigned char *iv, size_t s, void *ctx, printout_byte_array print, printout_uint_array print_uint) { Context_ctr* context; INFOTECS_ASSERT(sizeof(Context_ctr)<=kCtr89ContextLen); @@ -464,7 +464,7 @@ static int init_ctr_89_impl(unsigned char* key, unsigned char *iv, size_t s, voi return 0; } -int DLL_IMPORT init_ctr_89(unsigned char* key, unsigned char *iv, size_t s, void *ctx, printout_byte_array print, printout_uint_array print_uint) +int DLL_IMPORT init_ctr_89(unsigned char* key, const unsigned char *iv, size_t s, void *ctx, printout_byte_array print, printout_uint_array print_uint) { if(SelfTestGost89Ctr()) return -1; @@ -499,7 +499,7 @@ void DLL_IMPORT free_ctr(void* ctx) } } -static int init_ofb_14_impl(unsigned char *key, void *ctx, size_t s, unsigned char *iv, size_t ivLength, printout_byte_array print, printout_uint_array print_uint) +static int init_ofb_14_impl(unsigned char *key, void *ctx, size_t s, const unsigned char *iv, size_t ivLength, printout_byte_array print, printout_uint_array print_uint) { Context_ofb* context; INFOTECS_ASSERT(sizeof(Context_ofb)<=kOfb14ContextLen); @@ -546,7 +546,7 @@ int DLL_IMPORT init_ofb_14(unsigned char *key, void *ctx, size_t s, const unsign return init_ofb_14_impl(key, ctx, s, iv, ivLength, print, print_uint); } -static int init_ofb_89_impl(unsigned char *key, void *ctx, size_t s, unsigned char *iv, size_t ivLength, printout_byte_array print, printout_uint_array print_uint) +static int init_ofb_89_impl(unsigned char *key, void *ctx, size_t s, const unsigned char *iv, size_t ivLength, printout_byte_array print, printout_uint_array print_uint) { Context_ofb* context; INFOTECS_ASSERT(sizeof(Context_ofb)<=kOfb89ContextLen); @@ -584,7 +584,7 @@ static int init_ofb_89_impl(unsigned char *key, void *ctx, size_t s, unsigned ch return 0; } -int DLL_IMPORT init_ofb_89(unsigned char *key, void *ctx, size_t s, unsigned char *iv, size_t ivLength, printout_byte_array print, printout_uint_array print_uint) +int DLL_IMPORT init_ofb_89(unsigned char *key, void *ctx, size_t s, const unsigned char *iv, size_t ivLength, printout_byte_array print, printout_uint_array print_uint) { if(SelfTestGost89Ofb()) return -1; @@ -626,7 +626,7 @@ void DLL_IMPORT free_ofb(void* ctx) } -static int init_cfb_14_impl(unsigned char *key, void *ctx, size_t s, unsigned char *iv, size_t ivLength, printout_byte_array print, printout_uint_array print_uint) +static int init_cfb_14_impl(unsigned char *key, void *ctx, size_t s, const unsigned char *iv, size_t ivLength, printout_byte_array print, printout_uint_array print_uint) { Context_cfb* context; INFOTECS_ASSERT(sizeof(Context_cfb)<=kCfb14ContextLen); @@ -665,14 +665,14 @@ static int init_cfb_14_impl(unsigned char *key, void *ctx, size_t s, unsigned ch return 0; } -int DLL_IMPORT init_cfb_14(unsigned char *key, void *ctx, size_t s, unsigned char *iv, size_t ivLength, printout_byte_array print, printout_uint_array print_uint) +int DLL_IMPORT init_cfb_14(unsigned char *key, void *ctx, size_t s, const unsigned char *iv, size_t ivLength, printout_byte_array print, printout_uint_array print_uint) { if(SelfTestGost14Cfb()) return -1; return init_cfb_14_impl(key, ctx, s, iv, ivLength, print, print_uint); } -static int init_cfb_89_impl(unsigned char *key, void *ctx, size_t s, unsigned char *iv, size_t ivLength, printout_byte_array print, printout_uint_array print_uint) +static int init_cfb_89_impl(unsigned char *key, void *ctx, size_t s, const unsigned char *iv, size_t ivLength, printout_byte_array print, printout_uint_array print_uint) { Context_cfb* context; INFOTECS_ASSERT(sizeof(Context_cfb)<=kCfb89ContextLen); @@ -710,7 +710,7 @@ static int init_cfb_89_impl(unsigned char *key, void *ctx, size_t s, unsigned ch return 0; } -int DLL_IMPORT init_cfb_89(unsigned char *key, void *ctx, size_t s, unsigned char *iv, size_t ivLength, printout_byte_array print, printout_uint_array print_uint) +int DLL_IMPORT init_cfb_89(unsigned char *key, void *ctx, size_t s, const unsigned char *iv, size_t ivLength, printout_byte_array print, printout_uint_array print_uint) { if(SelfTestGost89Cfb()) return -1; @@ -1047,7 +1047,7 @@ int DLL_IMPORT decrypt_ecb(void *ctx, const unsigned char *indata, unsigned char return 0; } -static void PackBlock(unsigned char* a, size_t aLen, unsigned char* b, unsigned char* r, size_t rLen) +static void PackBlock(unsigned char* a, size_t aLen, const unsigned char* b, unsigned char* r, size_t rLen) { memcpy(r, a, aLen); memcpy(r + aLen, b, rLen - aLen); diff --git a/dap-sdk/crypto/src/GOST/block_cipher.h b/dap-sdk/crypto/src/GOST/block_cipher.h index 4a6315ee1540c59ea0fc4fa651836721161e9212..00f60cc5643dbdbc8b6db944c1d11b407ef1ae55 100644 --- a/dap-sdk/crypto/src/GOST/block_cipher.h +++ b/dap-sdk/crypto/src/GOST/block_cipher.h @@ -105,7 +105,7 @@ void DLL_IMPORT free_ecb(void* ctx); * @return 0 еÑли вÑе преобразование прошло уÑпешно * @return -1 еÑли произошла ошибка */ -int DLL_IMPORT init_cbc_14(unsigned char *key, void* ctx, unsigned char *iv, size_t ivLength, printout_byte_array print, printout_uint_array print_uint); +int DLL_IMPORT init_cbc_14(unsigned char *key, void* ctx, const unsigned char *iv, size_t ivLength, printout_byte_array print, printout_uint_array print_uint); /** @brief Ð˜Ð½Ð¸Ñ†Ð¸Ð°Ð»Ð¸Ð·Ð°Ñ†Ð¸Ñ ÐºÐ¾Ð½Ñ‚ÐµÐºÑта ÑˆÐ¸Ñ„Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ð² режиме CBC Ð´Ð»Ñ Ð°Ð»Ð³Ð¾Ñ€Ð¸Ñ‚Ð¼Ð° 28147-89 * @@ -118,7 +118,7 @@ int DLL_IMPORT init_cbc_14(unsigned char *key, void* ctx, unsigned char *iv, si * @return 0 еÑли вÑе преобразование прошло уÑпешно * @return -1 еÑли произошла ошибка */ -int DLL_IMPORT init_cbc_89(unsigned char *key, void* ctx, unsigned char *iv, size_t ivLength, printout_byte_array print, printout_uint_array print_uint); +int DLL_IMPORT init_cbc_89(unsigned char *key, void* ctx, const unsigned char *iv, size_t ivLength, printout_byte_array print, printout_uint_array print_uint); /** @brief Удаление контекÑта cbc * @@ -139,7 +139,7 @@ void DLL_IMPORT free_cbc(void* ctx); * @return 0 еÑли вÑе преобразование прошло уÑпешно * @return -1 еÑли произошла ошибка */ -int DLL_IMPORT init_ctr_14(unsigned char* key, unsigned char *iv, size_t length, void *ctx, printout_byte_array print, printout_uint_array print_uint); +int DLL_IMPORT init_ctr_14(unsigned char* key, const unsigned char *iv, size_t length, void *ctx, printout_byte_array print, printout_uint_array print_uint); /** @brief Ð˜Ð½Ð¸Ñ†Ð¸Ð°Ð»Ð¸Ð·Ð°Ñ†Ð¸Ñ ÐºÐ¾Ð½Ñ‚ÐµÐºÑта ÑˆÐ¸Ñ„Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ð² режиме CTR Ð´Ð»Ñ Ð°Ð»Ð³Ð¾Ñ€Ð¸Ñ‚Ð¼Ð° 28147-89 * @@ -152,7 +152,7 @@ int DLL_IMPORT init_ctr_14(unsigned char* key, unsigned char *iv, size_t length, * @return 0 еÑли вÑе преобразование прошло уÑпешно * @return -1 еÑли произошла ошибка */ -int DLL_IMPORT init_ctr_89(unsigned char* key, unsigned char *iv, size_t length, void *ctx, printout_byte_array print, printout_uint_array print_uint); +int DLL_IMPORT init_ctr_89(unsigned char* key, const unsigned char *iv, size_t length, void *ctx, printout_byte_array print, printout_uint_array print_uint); /** @brief Удаление контекÑта ctr * @@ -188,7 +188,7 @@ int DLL_IMPORT init_ofb_14(unsigned char *key, void *ctx, size_t s, const unsign * @return 0 еÑли вÑе преобразование прошло уÑпешно * @return -1 еÑли произошла ошибка */ -int DLL_IMPORT init_ofb_89(unsigned char *key, void *ctx, size_t s, unsigned char *iv, size_t ivLength, printout_byte_array print, printout_uint_array print_uint); +int DLL_IMPORT init_ofb_89(unsigned char *key, void *ctx, size_t s, const unsigned char *iv, size_t ivLength, printout_byte_array print, printout_uint_array print_uint); /** @brief Удаление контекÑта ofb * @@ -210,7 +210,7 @@ void DLL_IMPORT free_ofb(void* ctx); * @return 0 еÑли вÑе преобразование прошло уÑпешно * @return -1 еÑли произошла ошибка */ -int DLL_IMPORT init_cfb_14(unsigned char *key, void *ctx, size_t s, unsigned char *iv, size_t ivLength, printout_byte_array print, printout_uint_array print_uint); +int DLL_IMPORT init_cfb_14(unsigned char *key, void *ctx, size_t s, const unsigned char *iv, size_t ivLength, printout_byte_array print, printout_uint_array print_uint); /** @brief Ð˜Ð½Ð¸Ñ†Ð¸Ð°Ð»Ð¸Ð·Ð°Ñ†Ð¸Ñ ÐºÐ¾Ð½Ñ‚ÐµÐºÑта ÑˆÐ¸Ñ„Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ð² режиме CFB Ð´Ð»Ñ Ð°Ð»Ð³Ð¾Ñ€Ð¸Ñ‚Ð¼Ð° 28147-89 * @@ -224,7 +224,7 @@ int DLL_IMPORT init_cfb_14(unsigned char *key, void *ctx, size_t s, unsigned cha * @return 0 еÑли вÑе преобразование прошло уÑпешно * @return -1 еÑли произошла ошибка */ -int DLL_IMPORT init_cfb_89(unsigned char *key, void *ctx, size_t s, unsigned char *iv, size_t ivLength, printout_byte_array print, printout_uint_array print_uint); +int DLL_IMPORT init_cfb_89(unsigned char *key, void *ctx, size_t s, const unsigned char *iv, size_t ivLength, printout_byte_array print, printout_uint_array print_uint); /** @brief Удаление контекÑта cfb * diff --git a/dap-sdk/crypto/src/GOST/callback_print.h b/dap-sdk/crypto/src/GOST/callback_print.h index 01e387f0db946f85d4eec859e0f26229362aa236..5d76323e3e3e74587ac7187190786d900bbaa22d 100644 --- a/dap-sdk/crypto/src/GOST/callback_print.h +++ b/dap-sdk/crypto/src/GOST/callback_print.h @@ -10,9 +10,9 @@ #include "dll_import.h" /** @brief callback Ð´Ð»Ñ Ð²Ñ‹Ð²Ð¾Ð´Ð° маÑÑива byte */ -typedef void (DLL_IMPORT *printout_byte_array)(const char* text, unsigned char* value, unsigned int valueSize); +typedef void (DLL_IMPORT *printout_byte_array)(const char* text, const unsigned char* value, unsigned int valueSize); /** @brief callback Ð´Ð»Ñ Ð²Ñ‹Ð²Ð¾Ð´Ð° маÑÑива unsigned int32 */ -typedef void (DLL_IMPORT *printout_uint_array)(const char* text, unsigned int* value, unsigned int valueSize); +typedef void (DLL_IMPORT *printout_uint_array)(const char* text, const unsigned int* value, unsigned int valueSize); #endif diff --git a/dap-sdk/crypto/src/GOST/test_data.inc b/dap-sdk/crypto/src/GOST/test_data.inc deleted file mode 100644 index 94d893eb745e313b9bc06c72d25edfdf75b2b76d..0000000000000000000000000000000000000000 --- a/dap-sdk/crypto/src/GOST/test_data.inc +++ /dev/null @@ -1,313 +0,0 @@ -/*---------------------------------------------------------------------- - * теÑтовые Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð´Ð»Ñ Ð°Ð»Ð³Ð¾Ñ€Ð¸Ñ‚Ð¼Ð° кузнечик из Ñтандарта - */ - -/* теÑтовые Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð¿Ñ€ÐµÐ¾Ð±Ñ€Ð°Ð·Ð¾Ð²Ð°Ð½Ð¸Ñ S */ -unsigned char kSData[5][kBlockLen14] = -{ - {0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 0x99, 0x88, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x00}, - {0xb6, 0x6c, 0xd8, 0x88, 0x7d, 0x38, 0xe8, 0xd7, 0x77, 0x65, 0xae, 0xea, 0x0c, 0x9a, 0x7e, 0xfc}, - {0x55, 0x9d, 0x8d, 0xd7, 0xbd, 0x06, 0xcb, 0xfe, 0x7e, 0x7b, 0x26, 0x25, 0x23, 0x28, 0x0d, 0x39}, - {0x0c, 0x33, 0x22, 0xfe, 0xd5, 0x31, 0xe4, 0x63, 0x0d, 0x80, 0xef, 0x5c, 0x5a, 0x81, 0xc5, 0x0b}, - {0x23, 0xae, 0x65, 0x63, 0x3f, 0x84, 0x2d, 0x29, 0xc5, 0xdf, 0x52, 0x9c, 0x13, 0xf5, 0xac, 0xda} -}; - -/* теÑтовые Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð¿Ñ€ÐµÐ¾Ð±Ñ€Ð°Ð·Ð¾Ð²Ð°Ð½Ð¸Ñ R */ -unsigned char kRData[5][kBlockLen14] = -{ - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00}, - {0x94, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, - {0xa5, 0x94, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x64, 0xa5, 0x94, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x0d, 0x64, 0xa5, 0x94, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} -}; - -/* теÑтовые Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð¿Ñ€ÐµÐ¾Ð±Ñ€Ð°Ð·Ð¾Ð²Ð°Ð½Ð¸Ñ L */ -unsigned char kLData[5][kBlockLen14] = -{ - {0x64, 0xa5, 0x94, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0xd4, 0x56, 0x58, 0x4d, 0xd0, 0xe3, 0xe8, 0x4c, 0xc3, 0x16, 0x6e, 0x4b, 0x7f, 0xa2, 0x89, 0x0d}, - {0x79, 0xd2, 0x62, 0x21, 0xb8, 0x7b, 0x58, 0x4c, 0xd4, 0x2f, 0xbc, 0x4f, 0xfe, 0xa5, 0xde, 0x9a}, - {0x0e, 0x93, 0x69, 0x1a, 0x0c, 0xfc, 0x60, 0x40, 0x8b, 0x7b, 0x68, 0xf6, 0x6b, 0x51, 0x3c, 0x13}, - {0xe6, 0xa8, 0x09, 0x4f, 0xee, 0x0a, 0xa2, 0x04, 0xfd, 0x97, 0xbc, 0xb0, 0xb4, 0x4b, 0x85, 0x80} -}; - -/* теÑтовые Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ñ€Ð°Ð·Ð²ÐµÑ€Ð½ÑƒÑ‚Ñ‹Ñ… ключей */ -static const unsigned char kKData[10][kBlockLen14] = -{ - {0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77}, - {0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef}, - {0xdb, 0x31, 0x48, 0x53, 0x15, 0x69, 0x43, 0x43, 0x22, 0x8d, 0x6a, 0xef, 0x8c, 0xc7, 0x8c, 0x44}, - {0x3d, 0x45, 0x53, 0xd8, 0xe9, 0xcf, 0xec, 0x68, 0x15, 0xeb, 0xad, 0xc4, 0x0a, 0x9f, 0xfd, 0x04}, - {0x57, 0x64, 0x64, 0x68, 0xc4, 0x4a, 0x5e, 0x28, 0xd3, 0xe5, 0x92, 0x46, 0xf4, 0x29, 0xf1, 0xac}, - {0xbd, 0x07, 0x94, 0x35, 0x16, 0x5c, 0x64, 0x32, 0xb5, 0x32, 0xe8, 0x28, 0x34, 0xda, 0x58, 0x1b}, - {0x51, 0xe6, 0x40, 0x75, 0x7e, 0x87, 0x45, 0xde, 0x70, 0x57, 0x27, 0x26, 0x5a, 0x00, 0x98, 0xb1}, - {0x5a, 0x79, 0x25, 0x01, 0x7b, 0x9f, 0xdd, 0x3e, 0xd7, 0x2a, 0x91, 0xa2, 0x22, 0x86, 0xf9, 0x84}, - {0xbb, 0x44, 0xe2, 0x53, 0x78, 0xc7, 0x31, 0x23, 0xa5, 0xf3, 0x2f, 0x73, 0xcd, 0xb6, 0xe5, 0x17}, - {0x72, 0xe9, 0xdd, 0x74, 0x16, 0xbc, 0xf4, 0x5b, 0x75, 0x5d, 0xba, 0xa8, 0x8e, 0x4a, 0x40, 0x43}, -}; - -/* теÑтовые Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð¼Ð°Ñтер-ключа */ -unsigned char kMasterKeyData[32] = -{ - 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66,0x77, - 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef -}; - -/* значение открытого текÑта */ -unsigned char kPlainTextData[] = -{ - 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x00, 0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 0x99, 0x88 -}; - - -/* значение шифротекÑта */ -unsigned char kChipherTextData[] = -{ - 0x7f, 0x67, 0x9d, 0x90, 0xbe, 0xbc, 0x24, 0x30, 0x5a, 0x46, 0x8d, 0x42, 0xb9, 0xd4, 0xed, 0xcd -}; - -/* теÑтовые Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð¾Ð±Ñ€Ð°Ñ‚Ð½Ð¾Ð³Ð¾ Ð¿Ñ€ÐµÐ¾Ð±Ñ€Ð°Ð·Ð¾Ð²Ð°Ð½Ð¸Ñ L */ -unsigned char kReverseLData[2][kBlockLen14] = -{ - {0x0d, 0x8e, 0x40, 0xe4, 0xa8, 0x00, 0xd0, 0x6b, 0x2f, 0x1b, 0x37, 0xea, 0x37, 0x9e, 0xad, 0x8e}, - {0x8a, 0x6b, 0x93, 0x0a, 0x52, 0x21, 0x1b, 0x45, 0xc5, 0xba, 0xa4, 0x3f, 0xf8, 0xb9, 0x13, 0x19}, -}; - -/* теÑтовые Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð¾Ð±Ñ€Ð°Ñ‚Ð½Ð¾Ð³Ð¾ Ð¿Ñ€ÐµÐ¾Ð±Ñ€Ð°Ð·Ð¾Ð²Ð°Ð½Ð¸Ñ LSX */ -unsigned char kReverseLSXData[10][kBlockLen14] = -{ - {0x8a, 0x6b, 0x93, 0x0a, 0x52, 0x21, 0x1b, 0x45, 0xc5, 0xba, 0xa4, 0x3f, 0xf8, 0xb9, 0x13, 0x19}, - {0x76, 0xca, 0x14, 0x9e, 0xef, 0x27, 0xdl, 0xbl, 0x0d, 0x17, 0xe3, 0xd5, 0xd6, 0x8e, 0x5a, 0x72}, - {0x5d, 0x9b, 0x06, 0xd4, 0x1b, 0x9d, 0x1d, 0x2d, 0x04, 0xdf, 0x77, 0x55, 0x36, 0x3e, 0x94, 0xa9}, - {0x79, 0x48, 0x71, 0x92, 0xaa, 0x45, 0x70, 0x9c, 0x11, 0x55, 0x59, 0xd6, 0xe9, 0x28, 0x0f, 0x6e}, - {0xae, 0x50, 0x69, 0x24, 0xc8, 0xce, 0x33, 0x1b, 0xb9, 0x18, 0xfc, 0x5b, 0xdf, 0xbl, 0x95, 0xfa}, - {0xbb, 0xff, 0xbf, 0xc8, 0x93, 0x9e, 0xaa, 0xff, 0xaf, 0xb8, 0xe2, 0x27, 0x69, 0xe3, 0x23, 0xaa}, - {0x3c, 0xc2, 0xf0, 0x7c, 0xc0, 0x7a, 0x8b, 0xec, 0x0f, 0x3e, 0xa0, 0xed, 0x2a, 0xe3, 0x3e, 0x4a}, - {0xf3, 0x6f, 0x01, 0x29, 0x1d, 0x0b, 0x96, 0xd5, 0x91, 0xe2, 0x28, 0xb7, 0x2d, 0x01, 0x1c, 0x36}, - {0x1c, 0x4b, 0x0c, 0x1e, 0x95, 0x01, 0x82, 0xbl, 0xce, 0x69, 0x6a, 0xf5, 0xc0, 0xbf, 0xc5, 0xdf}, - {0x99, 0xbb, 0x99, 0xff, 0x99, 0xbb, 0x99, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff} -}; - -unsigned char kGost14SV[8] = -{ - 0x12, 0x34, 0x56, 0x78, 0x90, 0xab, 0xcd, 0xef -}; - -unsigned char kGost14PlainText[64] = -{ - 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x00, 0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 0x99, 0x88, - 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xee, 0xff, 0x0a, - 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xee, 0xff, 0x0a, 0x00, - 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xee, 0xff, 0x0a, 0x00, 0x11 -}; - -unsigned char kGost14EcbEncText[64] = -{ - 0x7f, 0x67, 0x9d, 0x90, 0xbe, 0xbc, 0x24, 0x30, 0x5a, 0x46, 0x8d, 0x42, 0xb9, 0xd4, 0xed, 0xcd, - 0xb4, 0x29, 0x91, 0x2c, 0x6e, 0x00, 0x32, 0xf9, 0x28, 0x54, 0x52, 0xd7, 0x67, 0x18, 0xd0, 0x8b, - 0xf0, 0xca, 0x33, 0x54, 0x9d, 0x24, 0x7c, 0xee, 0xf3, 0xf5, 0xa5, 0x31, 0x3b, 0xd4, 0xb1, 0x57, - 0xd0, 0xb0, 0x9c, 0xcd, 0xe8, 0x30, 0xb9, 0xeb, 0x3a, 0x02, 0xc4, 0xc5, 0xaa, 0x8a, 0xda, 0x98 -}; - - -unsigned char kGost14CtrSV[16] = -{ - 0x12, 0x34, 0x56, 0x78, 0x90, 0xab, 0xce, 0xf0, 0xa1, 0xb2, 0xc3, 0xd4, 0xe5, 0xf0, 0x01, 0x12 -}; - -unsigned char kGost14CtrC[64] = -{ - 0xf1, 0x95, 0xd8, 0xbe, 0xc1, 0x0e, 0xd1, 0xdb, 0xd5, 0x7b, 0x5f, 0xa2, 0x40, 0xbd, 0xa1, 0xb8, - 0x85, 0xee, 0xe7, 0x33, 0xf6, 0xa1, 0x3e, 0x5d, 0xf3, 0x3c, 0xe4, 0xb3, 0x3c, 0x45, 0xde, 0xe4, - 0xa5, 0xea, 0xe8, 0x8b, 0xe6, 0x35, 0x6e, 0xd3, 0xd5, 0xe8, 0x77, 0xf1, 0x35, 0x64, 0xa3, 0xa5, - 0xcb, 0x91, 0xfa, 0xb1, 0xf2, 0x0c, 0xba, 0xb6, 0xd1, 0xc6, 0xd1, 0x58, 0x20, 0xbd, 0xba, 0x73 -}; - -unsigned char kGost14OfbSV[32] = -{ - 0x12, 0x34, 0x56, 0x78, 0x90, 0xab, 0xce, 0xf0, 0xa1, 0xb2, 0xc3, 0xd4, 0xe5, 0xf0, 0x01, 0x12, - 0x23, 0x34, 0x45, 0x56, 0x67, 0x78, 0x89, 0x90, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19 -}; - -unsigned char kGost14OfbC[64] = -{ - 0x81, 0x80, 0x0a, 0x59, 0xb1, 0x84, 0x2b, 0x24, 0xff, 0x1f, 0x79, 0x5e, 0x89, 0x7a, 0xbd, 0x95, - 0xed, 0x5b, 0x47, 0xa7, 0x04, 0x8c, 0xfa, 0xb4, 0x8f, 0xb5, 0x21, 0x36, 0x9d, 0x93, 0x26, 0xbf, - 0x66, 0xa2, 0x57, 0xac, 0x3c, 0xa0, 0xb8, 0xb1, 0xc8, 0x0f, 0xe7, 0xfc, 0x10, 0x28, 0x8a, 0x13, - 0x20, 0x3e, 0xbb, 0xc0, 0x66, 0x13, 0x86, 0x60, 0xa0, 0x29, 0x22, 0x43, 0xf6, 0x90, 0x31, 0x50 -}; - -unsigned char kGost14CbcSV[32] = -{ - 0x12, 0x34, 0x56, 0x78, 0x90, 0xab, 0xce, 0xf0, 0xa1, 0xb2, 0xc3, 0xd4, 0xe5, 0xf0, 0x01, 0x12, - 0x23, 0x34, 0x45, 0x56, 0x67, 0x78, 0x89, 0x90, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19 -}; - -unsigned char kGost14CbcC[64] = -{ - 0x68, 0x99, 0x72, 0xd4, 0xa0, 0x85, 0xfa, 0x4d, 0x90, 0xe5, 0x2e, 0x3d, 0x6d, 0x7d, 0xcc, 0x27, - 0x28, 0x26, 0xe6, 0x61, 0xb4, 0x78, 0xec, 0xa6, 0xaf, 0x1e, 0x8e, 0x44, 0x8d, 0x5e, 0xa5, 0xac, - 0xfe, 0x7b, 0xab, 0xf1, 0xe9, 0x19, 0x99, 0xe8, 0x56, 0x40, 0xe8, 0xb0, 0xf4, 0x9d, 0x90, 0xd0, - 0x16, 0x76, 0x88, 0x06, 0x5a, 0x89, 0x5c, 0x63, 0x1a, 0x2d, 0x9a, 0x15, 0x60, 0xb6, 0x39, 0x70 -}; - -unsigned char kGost14CfbSV[32] = -{ - 0x12, 0x34, 0x56, 0x78, 0x90, 0xab, 0xce, 0xf0, 0xa1, 0xb2, 0xc3, 0xd4, 0xe5, 0xf0, 0x01, 0x12, - 0x23, 0x34, 0x45, 0x56, 0x67, 0x78, 0x89, 0x90, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19 -}; - -unsigned char kGost14CfbC[64] = -{ - 0x81, 0x80, 0x0a, 0x59, 0xb1, 0x84, 0x2b, 0x24, 0xff, 0x1f, 0x79, 0x5e, 0x89, 0x7a, 0xbd, 0x95, - 0xed, 0x5b, 0x47, 0xa7, 0x04, 0x8c, 0xfa, 0xb4, 0x8f, 0xb5, 0x21, 0x36, 0x9d, 0x93, 0x26, 0xbf, - 0x79, 0xf2, 0xa8, 0xeb, 0x5c, 0xc6, 0x8d, 0x38, 0x84, 0x2d, 0x26, 0x4e, 0x97, 0xa2, 0x38, 0xb5, - 0x4f, 0xfe, 0xbe, 0xcd, 0x4e, 0x92, 0x2d, 0xe6, 0xc7, 0x5b, 0xd9, 0xdd, 0x44, 0xfb, 0xf4, 0xd1 -}; - -unsigned char kGost14ImitS[8] = -{ - 0x33, 0x6f, 0x4d, 0x29, 0x60, 0x59, 0xfb, 0xe3 -}; - - - - -/* -------------------------------------------------------- */ - -unsigned char kMasterKeyGost89[] = -{ - 0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 0x99, 0x88, - 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, 0x00, - 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, - 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff -}; - -/* теÑтовые Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð¸Ð· Ñтандарты Ð´Ð»Ñ Ð°Ð»Ð³Ð¾Ñ€Ð¸Ñ‚Ð¼Ð° 89го года */ -unsigned char kGost89StandartPlainText[] = -{ - 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 -}; - -unsigned char kGost89StandartEncrText[] = -{ - 0x4e, 0xe9, 0x01, 0xe5, 0xc2, 0xd8, 0xca, 0x3d -}; - -/* теÑтовые Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð´Ð»Ñ Ð¿Ñ€ÐµÐ¾Ð±Ñ€Ð°Ð·Ð¾Ð²Ð°Ð½Ð¸Ñ t, опиÑанного в Ñтандарте */ -unsigned int kTData[5] = -{ - 0xfdb97531, 0x2a196f34, 0xebd9f03a, 0xb039bb3d, 0x68695433 -}; - -/* теÑтовые Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð´Ð»Ñ Ð¿Ñ€ÐµÐ¾Ð±Ñ€Ð°Ð·Ð¾Ð²Ð°Ð½Ð¸Ñ g, опиÑанного в Ñтандарте */ -unsigned int kgData[4][3] = -{ - {0x87654321, 0xfedcba98, 0xfdcbc20c}, - {0xfdcbc20c, 0x87654321, 0x7e791a4b}, - {0x7e791a4b, 0xfdcbc20c, 0xc76549ec}, - {0xc76549ec, 0x7e791a4b, 0x9791c849} -}; - -unsigned char kGost89PlaintText[32] = -{ - 0x92, 0xde, 0xf0, 0x6b, 0x3c, 0x13, 0x0a, 0x59, - 0xdb, 0x54, 0xc7, 0x04, 0xf8, 0x18, 0x9d, 0x20, - 0x4a, 0x98, 0xfb, 0x2e, 0x67, 0xa8, 0x02, 0x4c, - 0x89, 0x12, 0x40, 0x9b, 0x17, 0xb5, 0x7e, 0x41, -}; - -unsigned char kGost89EcbC[32] = -{ - 0x2b, 0x07, 0x3f, 0x04, 0x94, 0xf3, 0x72, 0xa0, - 0xde, 0x70, 0xe7, 0x15, 0xd3, 0x55, 0x6e, 0x48, - 0x11, 0xd8, 0xd9, 0xe9, 0xea, 0xcf, 0xbc, 0x1e, - 0x7c, 0x68, 0x26, 0x09, 0x96, 0xc6, 0x7e, 0xfb -}; - -unsigned char kGost89CtrSV[4] = -{ - 0x12, 0x34, 0x56, 0x78 -}; - -unsigned char kGost89CtrC[32] = -{ - 0x4e, 0x98, 0x11, 0x0c, 0x97, 0xb7, 0xb9, 0x3c, - 0x3e, 0x25, 0x0d, 0x93, 0xd6, 0xe8, 0x5d, 0x69, - 0x13, 0x6d, 0x86, 0x88, 0x07, 0xb2, 0xdb, 0xef, - 0x56, 0x8e, 0xb6, 0x80, 0xab, 0x52, 0xa1, 0x2d -}; - -unsigned char kGost89OfbSV[16] = -{ - 0x12, 0x34, 0x56, 0x78, 0x90, 0xab, 0xcd, 0xef, - 0x23, 0x45, 0x67, 0x89, 0x0a, 0xbc, 0xde, 0xf1 -}; - -unsigned char kGost89OfbC[32] = -{ - 0xdb, 0x37, 0xe0, 0xe2, 0x66, 0x90, 0x3c, 0x83, - 0x0d, 0x46, 0x64, 0x4c, 0x1f, 0x9a, 0x08, 0x9c, - 0xa0, 0xf8, 0x30, 0x62, 0x43, 0x0e, 0x32, 0x7e, - 0xc8, 0x24, 0xef, 0xb8, 0xbd, 0x4f, 0xdb, 0x05 -}; - - -unsigned char kGost89CbcSV[24] = -{ - 0x12, 0x34, 0x56, 0x78, 0x90, 0xab, 0xcd, 0xef, - 0x23, 0x45, 0x67, 0x89, 0x0a, 0xbc, 0xde, 0xf1, - 0x34, 0x56, 0x78, 0x90, 0xab, 0xcd, 0xef, 0x12, -}; - -unsigned char kGost89CbcC[32] = -{ - 0x96, 0xd1, 0xb0, 0x5e, 0xea, 0x68, 0x39, 0x19, - 0xaf, 0xf7, 0x61, 0x29, 0xab, 0xb9, 0x37, 0xb9, - 0x50, 0x58, 0xb4, 0xa1, 0xc4, 0xbc, 0x00, 0x19, - 0x20, 0xb7, 0x8b, 0x1a, 0x7c, 0xd7, 0xe6, 0x67, -}; - -unsigned char kGost89CfbSV[16] = -{ - 0x12, 0x34, 0x56, 0x78, 0x90, 0xab, 0xcd, 0xef, - 0x23, 0x45, 0x67, 0x89, 0x0a, 0xbc, 0xde, 0xf1 -}; - -unsigned char kGost89CfbC[32] = -{ - 0xdb, 0x37, 0xe0, 0xe2, 0x66, 0x90, 0x3c, 0x83, - 0x0d, 0x46, 0x64, 0x4c, 0x1f, 0x9a, 0x08, 0x9c, - 0x24, 0xbd, 0xd2, 0x03, 0x53, 0x15, 0xd3, 0x8b, - 0xbc, 0xc0, 0x32, 0x14, 0x21, 0x07, 0x55, 0x05 -}; - -unsigned char kGost89ImitS[8] = -{ - 0x15, 0x4e, 0x72, 0x10, 0x20, 0x30, 0xc5, 0xbb -}; - -/* ----------------------------------------------------- */ - -unsigned char kPaddingText[16] = -{ - 2, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -}; - -unsigned char kPaddingText2[32] = -{ - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -}; - -unsigned char paddingBufferText[16] = -{ - 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -}; - -unsigned char paddingBufferText2[32] = -{ - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -}; diff --git a/dap-sdk/crypto/src/GOST/testgost.c b/dap-sdk/crypto/src/GOST/testgost.c deleted file mode 100644 index 289b71abc9ec45ea62796e553ee17293f2c0a9da..0000000000000000000000000000000000000000 --- a/dap-sdk/crypto/src/GOST/testgost.c +++ /dev/null @@ -1,906 +0,0 @@ -/** @file - * @brief Ð ÐµÐ°Ð»Ð¸Ð·Ð°Ñ†Ð¸Ñ Ñ„ÑƒÐ½ÐºÑ†Ð¸Ð¹ теÑÑ‚Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ð°Ð»Ð³Ð¾Ñ€Ð¸Ñ‚Ð¼Ð¾Ð² "кузнечик" и 28147-89. Ртакже режимов работы блочных шифров - * - * @copyright InfoTeCS. All rights reserved. - */ - -#include <memory.h> - -#include "28147_14.h" -#include "block_cipher.h" -#include "28147_89.h" -#include "test_data.inc" -#include "print_data.h" - -/** @brief размер теÑтовых данных Ð´Ð»Ñ Ð°Ð»Ð³Ð¾Ñ€Ð¸Ñ‚Ð¼Ð° "кузнечик" */ -#define textLen14 sizeof(kGost14PlainText) - -/** @brief размер теÑтовых данных Ð´Ð»Ñ Ð°Ð»Ð³Ð¾Ñ€Ð¸Ñ‚Ð¼Ð° "28147-89" */ -#define textLen89 sizeof(kGost89PlaintText) - -/** @brief теÑтирование Ð¿Ñ€ÐµÐ¾Ð±Ñ€Ð°Ð·Ð¾Ð²Ð°Ð½Ð¸Ñ S из алгоритма "кузнечик" */ -int testS() -{ - unsigned char tmp[kBlockLen14]; - unsigned int i; - - PrintLabel("Test S function start."); - - for(i = 0; i < 4; ++i) - { - funcS(kSData[i], tmp, 0); - - PrintBlockLeft("Test ", i+1); - PrintBlock("Input Value: ", kSData[i], kBlockLen14, kBlockLen14); - PrintEmptyLine(); - PrintBlock("Output Value: ", tmp, kBlockLen14, kBlockLen14); - PrintEmptyLine(); - PrintBlock("Control Value: ", kSData[i+1], kBlockLen14, kBlockLen14); - PrintEmptyLine(); - - if(memcmp(tmp, kSData[i+1], kBlockLen14)) - return -1; - } - - return 0; -} - -/** @brief теÑтирование Ð¿Ñ€ÐµÐ¾Ð±Ñ€Ð°Ð·Ð¾Ð²Ð°Ð½Ð¸Ñ R из алгоритма "кузнечик" */ -int testR() -{ - unsigned char tmp[kBlockLen14]; - int i; - - PrintLabel("Test R function start."); - - for(i =0; i < 4; ++i) - { - if(funcR(kRData[i], tmp, 0)) - return -1; - - PrintBlockLeft("Test ", i+1); - PrintBlock("Input Value: ", kRData[i], kBlockLen14, kBlockLen14); - PrintEmptyLine(); - PrintBlock("Output Value: ", tmp, kBlockLen14, kBlockLen14); - PrintEmptyLine(); - PrintBlock("Control Value: ", kRData[i+1], kBlockLen14, kBlockLen14); - PrintEmptyLine(); - - if(memcmp(tmp, kRData[i+1], kBlockLen14)) - return -1; - } - - return 0; -} - -/** @brief теÑтирование Ð¿Ñ€ÐµÐ¾Ð±Ñ€Ð°Ð·Ð¾Ð²Ð°Ð½Ð¸Ñ L из алгоритма "кузнечик" */ -int testL() -{ - unsigned char tmp[kBlockLen14]; - int i; - - PrintLabel("Test L function start."); - - for(i =0; i < 4; ++i) - { - if(funcL(kLData[i], tmp, 0)) - return -1; - - PrintBlockLeft("Test ", i+1); - PrintBlock("Input Value: ", kLData[i], kBlockLen14, kBlockLen14); - PrintEmptyLine(); - PrintBlock("Output Value: ", tmp, kBlockLen14, kBlockLen14); - PrintEmptyLine(); - PrintBlock("Control Value: ", kLData[i+1], kBlockLen14, kBlockLen14); - PrintEmptyLine(); - - if( memcmp(tmp, kLData[i+1], kBlockLen14)) - return -1; - } - return 0; -} - -/** @brief теÑтирование Ñ€Ð°Ð·Ð²Ð¾Ñ€Ð°Ñ‡Ð¸Ð²Ð°Ð½Ð¸Ñ ÐºÐ»ÑŽÑ‡Ð° из алгоритма "кузнечик" */ -int testExpandKey() -{ - const size_t keyLen = sizeof(kMasterKeyData)/sizeof(kMasterKeyData[0]); - unsigned char keys[160]; - int i; - - PrintLabel("Test Expand Key function start."); - - if(ExpandKey(kMasterKeyData, keys, 0)) - return -1; - - PrintBlock("Master Key: ", kMasterKeyData, keyLen, kBlockLen14); - PrintEmptyLine(); - - for(i = 0; i < 10; ++i) - { - PrintBlock("Output Key: ", keys+i*kBlockLen14, kBlockLen14, kBlockLen14); - PrintBlock("Control Key: ", (unsigned char*)kKData[i], kBlockLen14, kBlockLen14); - PrintEmptyLine(); - - if( memcmp(keys+i*kBlockLen14, kKData[i], kBlockLen14)) - return -1; - } - - return 0; -} - -/** @brief теÑтирование ÑˆÐ¸Ñ„Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ð¿Ð¾ алгоритму "кузнечик" */ -int testEncrypt() -{ - const size_t keyLen = sizeof(kMasterKeyData)/sizeof(kMasterKeyData[0]); - - unsigned char ctx[kEcb14ContextLen]; - unsigned char output[kBlockLen14]; - - PrintLabel("Test Encrypt start."); - - if(init_ecb_14(kMasterKeyData, ctx, 0, 0)) - return -1; - - if(encrypt_ecb(ctx, kPlainTextData, output, kBlockLen14)) - return -1; - - PrintBlock("Master Key: ", kMasterKeyData, keyLen, kBlockLen14); - PrintEmptyLine(); - PrintBlock("Input Value: ", kPlainTextData, kBlockLen14, kBlockLen14); - PrintEmptyLine(); - PrintBlock("Output Value: ", output, kBlockLen14, kBlockLen14); - PrintEmptyLine(); - PrintBlock("Control value: ", kChipherTextData, kBlockLen14, kBlockLen14); - PrintEmptyLine(); - - if( memcmp(output, kChipherTextData, kBlockLen14)) - return -1; - - return 0; -} - -/** @brief теÑтирование раÑÑˆÐ¸Ñ„Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ð¿Ð¾ алгоритму "кузнечик" */ -int testDecrypt() -{ - const size_t keyLen = sizeof(kMasterKeyData)/sizeof(kMasterKeyData[0]); - - unsigned char ctx[kEcb14ContextLen]; - unsigned char output[kBlockLen14]; - - PrintLabel("Test Decrypt start."); - - if(init_ecb_14(kMasterKeyData, ctx, 0, 0)) - return -1; - - if(decrypt_ecb(ctx, kChipherTextData, output, kBlockLen14)) - return -1; - - PrintBlock("Master Key: ", kMasterKeyData, keyLen, kBlockLen14); - PrintEmptyLine(); - PrintBlock("Input Value: ", kChipherTextData, kBlockLen14, kBlockLen14); - PrintEmptyLine(); - PrintBlock("Output Value: ", output, kBlockLen14, kBlockLen14); - PrintEmptyLine(); - PrintBlock("Control value: ", kPlainTextData, kBlockLen14, kBlockLen14); - PrintEmptyLine(); - - if( memcmp(output, kPlainTextData, kBlockLen14) ) - return -1; - - free_ecb(ctx); - - return 0; -} - -/** @brief теÑтирование шифроавание в режиме ecb по алгоритму "кузнечик" */ -int gost14_ECB_test() -{ - unsigned char ctx[kEcb14ContextLen]; - unsigned char output[textLen14]; - unsigned char outputE[textLen14]; - - PrintLabel("Ecb mode 28147-14 test start."); - - if(init_ecb_14(kMasterKeyData, ctx, print_array, print_uint_array)) - return -1; - - if(encrypt_ecb(ctx, kGost14PlainText, output, textLen14)) - return -1; - - PrintBlock("Master Key: ", kMasterKeyData, 32, kBlockLen14); - PrintEmptyLine(); - PrintLineLeft("Test Encrypt."); - PrintEmptyLine(); - PrintBlock("Input Value: ", kGost14PlainText, kBlockLen14, kBlockLen14); - PrintEmptyLine(); - PrintBlock("Output Value: ", output, kBlockLen14, kBlockLen14); - PrintEmptyLine(); - PrintBlock("Control value: ", kGost14EcbEncText, kBlockLen14, kBlockLen14); - PrintEmptyLine(); - - if( memcmp(output, kGost14EcbEncText, textLen14)) - return -1; - - if(init_ecb_14(kMasterKeyData, ctx, print_array, print_uint_array)) - return -1; - - if(decrypt_ecb(ctx, output, outputE, textLen14)) - return -1; - - PrintLineLeft("Test Decrypt."); - PrintEmptyLine(); - PrintBlock("Input Value: ", output, kBlockLen14, kBlockLen14); - PrintEmptyLine(); - PrintBlock("Output Value: ", outputE, kBlockLen14, kBlockLen14); - PrintEmptyLine(); - PrintBlock("Control value: ", kGost14PlainText, kBlockLen14, kBlockLen14); - PrintEmptyLine(); - - if( memcmp(outputE, kGost14PlainText, textLen14)) - return -1; - - free_ecb(ctx); - - return 0; -} - -/** @brief теÑтирование режима ctr алгоритма "кузнечик" */ -int gost14_CTR_test() -{ - const size_t svLen = sizeof(kGost14CtrSV); - - unsigned char outText[textLen14]; - unsigned char ctx[kCtr14ContextLen]; - - PrintLabel("CTR mode 28147-14 test start."); - - if(init_ctr_14(kMasterKeyData, kGost14CtrSV, svLen, ctx, print_array, print_uint_array)) - return -1; - - if(crypt_ctr(ctx, kGost14PlainText, outText, textLen14)) - return -1; - - free_ctr(ctx); - - PrintBlock("Master Key: ", kMasterKeyData, 32, kBlockLen14); - PrintEmptyLine(); - PrintBlock("SV: ", kGost14CtrSV, kBlockLen14, kBlockLen14); - PrintEmptyLine(); - PrintBlock("Input Value: ", kGost14PlainText, textLen14, kBlockLen14); - PrintEmptyLine(); - PrintBlock("Output Value: ", outText, textLen14, kBlockLen14); - PrintEmptyLine(); - PrintBlock("Control value: ", kGost14CtrC, textLen14, kBlockLen14); - PrintEmptyLine(); - - return memcmp(outText, kGost14CtrC, textLen14); -} - -/** @brief теÑтирование режима ofb алгоритма "кузнечик" */ -int gost14_OFB_test() -{ - const size_t svLen = sizeof(kGost14OfbSV); - - unsigned char outText[textLen14]; - unsigned char ctx[kOfb14ContextLen]; - - PrintLabel("OFB mode 28147-14 test start."); - - if(init_ofb_14(kMasterKeyData, ctx, kBlockLen14, kGost14OfbSV, svLen, print_array, print_uint_array)) - return -1; - - if(crypt_ofb(ctx, kGost14PlainText, outText, textLen14)) - return -1; - - free_ofb(ctx); - - PrintBlock("Master Key: ", kMasterKeyData, 32, kBlockLen14); - PrintEmptyLine(); - PrintBlock("SV: ", kGost14OfbSV, kBlockLen14, kBlockLen14); - PrintEmptyLine(); - PrintBlock("Input Value: ", kGost14PlainText, textLen14, kBlockLen14); - PrintEmptyLine(); - PrintBlock("Output Value: ", outText, textLen14, kBlockLen14); - PrintEmptyLine(); - PrintBlock("Control value: ", kGost14OfbC, textLen14, kBlockLen14); - PrintEmptyLine(); - - return memcmp(outText, kGost14OfbC, textLen14); -} - -/** @brief теÑтирование режима cbc алгоритма "кузнечик" */ -int gost14_CBC_test() -{ - const size_t svLen = sizeof(kGost14CbcSV); - - unsigned char outText[textLen14]; - unsigned char outTextDec[textLen14]; - unsigned char ctx[kCbc14ContextLen]; - - PrintLabel("CBC mode 28147-14 test start."); - - if(init_cbc_14(kMasterKeyData, ctx, kGost14CbcSV, svLen, print_array, print_uint_array)) - return -1; - - if(encrypt_cbc(ctx, kGost14PlainText, outText, textLen14)) - return -1; - - free_cbc(ctx); - - PrintBlock("Master Key: ", kMasterKeyData, 32, kBlockLen14); - PrintEmptyLine(); - PrintLineLeft("Test Encrypt."); - PrintEmptyLine(); - PrintBlock("SV: ", kGost14CbcSV, svLen, kBlockLen14); - PrintEmptyLine(); - PrintBlock("Input Value: ", kGost14PlainText, textLen14, kBlockLen14); - PrintEmptyLine(); - PrintBlock("Output Value: ", outText, textLen14, kBlockLen14); - PrintEmptyLine(); - PrintBlock("Control value: ", kGost14CbcC, textLen14, kBlockLen14); - PrintEmptyLine(); - - if(init_cbc_14(kMasterKeyData, ctx, kGost14CbcSV, svLen, print_array, print_uint_array)) - return -1; - - if(decrypt_cbc(ctx, outText, outTextDec, textLen14)) - return -1; - - free_cbc(ctx); - - PrintLineLeft("Test Decrypt."); - PrintEmptyLine(); - PrintBlock("Input Value: ", outText, textLen14, kBlockLen14); - PrintEmptyLine(); - PrintBlock("Output Value: ", outTextDec, textLen14, kBlockLen14); - PrintEmptyLine(); - PrintBlock("Control value: ", kGost14PlainText, textLen14, kBlockLen14); - PrintEmptyLine(); - - if(memcmp(outTextDec, kGost14PlainText, textLen14)) - return -1; - - return memcmp(outText, kGost14CbcC, textLen14); -} - -/** @brief теÑтирование режима cfb алгоритма "кузнечик" */ -int gost14_CFB_test() -{ - const size_t svLen = sizeof(kGost14CfbSV); - - unsigned char outText[textLen14]; - unsigned char outTextDec[textLen14]; - unsigned char ctx[kCfb14ContextLen]; - - PrintLabel("CFB mode 28147-14 test start."); - - if(init_cfb_14(kMasterKeyData, ctx, kBlockLen14, kGost14CfbSV, svLen, print_array, print_uint_array)) - return -1; - - if(encrypt_cfb(ctx, kGost14PlainText, outText, textLen89)) - return -1; - - if(memcmp(outText, kGost14CfbC, textLen89)) - return -1; - - PrintBlock("Master Key: ", kMasterKeyData, 32, kBlockLen14); - PrintEmptyLine(); - PrintBlock("SV: ", kGost14CfbSV, svLen, kBlockLen14); - PrintEmptyLine(); - PrintLineLeft("Test Encrypt."); - PrintEmptyLine(); - PrintBlock("Input Value: ", kGost14PlainText, textLen89, kBlockLen14); - PrintEmptyLine(); - PrintBlock("Output Value: ", outText, textLen89, kBlockLen14); - PrintEmptyLine(); - PrintBlock("Control value: ", kGost14CfbC, textLen89, kBlockLen14); - PrintEmptyLine(); - - free_cfb(ctx); - - if(init_cfb_14(kMasterKeyData, ctx, 16, kGost14CfbSV, svLen, print_array, print_uint_array)) - return -1; - - if(decrypt_cfb(ctx, outText, outTextDec, textLen89)) - return -1; - - PrintLineLeft("Test Decrypt."); - PrintEmptyLine(); - PrintBlock("Input Value: ", outText, textLen89, kBlockLen14); - PrintEmptyLine(); - PrintBlock("Output Value: ", outTextDec, textLen89, kBlockLen14); - PrintEmptyLine(); - PrintBlock("Control value: ", kGost14PlainText, textLen89, kBlockLen14); - PrintEmptyLine(); - - if(memcmp(outTextDec, kGost14PlainText, textLen89)) - return -1; - - free_cfb(ctx); - - return 0; -} - -/** @brief теÑтирование режима имитовÑтавки алгоритма "кузнечик" */ -int gost14_imita_test() -{ - const size_t imitLen = sizeof(kGost14ImitS); - unsigned char outText[16]; - unsigned char ctx[kImit14ContextLen]; - - PrintLabel("Imita mode 28147-14 test start."); - - if(init_imit_14(kMasterKeyData, kBlockLen14, ctx, print_array, print_uint_array)) - return -1; - - if(imit(ctx, kGost14PlainText, textLen14)) - return 0; - - done_imit(ctx, outText); - - PrintBlock("Input Value: ", kGost14PlainText, textLen14, kBlockLen14); - PrintEmptyLine(); - PrintBlock("Output Value: ", outText, imitLen, kBlockLen14); - PrintEmptyLine(); - PrintBlock("Control value: ", kGost14ImitS, imitLen, kBlockLen14); - PrintEmptyLine(); - - free_imit(ctx); - - return memcmp(outText, kGost14ImitS, imitLen); -} - -/** @brief теÑтирование режима ecb алгоритма 28147-89 */ -int gost89_ECB_test() -{ - unsigned char ctx[kEcb89ContextLen]; - unsigned char output[textLen89]; - unsigned char outputDec[textLen89]; - - PrintLabel("Ecb mode 28147-89 test start."); - - if(init_ecb_89(kMasterKeyGost89, ctx, print_array, print_uint_array)) - return -1; - - if(encrypt_ecb(ctx, kGost89PlaintText, output, textLen89)) - return -1; - - PrintBlock("Master Key: ", kMasterKeyGost89, 32, kBlockLen89); - PrintEmptyLine(); - PrintBlock("Input Value: ", kGost89PlaintText, textLen89, kBlockLen89); - PrintEmptyLine(); - PrintBlock("Output Value: ", output, textLen89, kBlockLen89); - PrintEmptyLine(); - PrintBlock("Control value: ", kGost89EcbC, textLen89, kBlockLen89); - PrintEmptyLine(); - - if(memcmp(output, kGost89EcbC, textLen89)) - return -1; - - free_ecb(ctx); - - if(init_ecb_89(kMasterKeyGost89, ctx, print_array, print_uint_array)) - return -1; - - if(decrypt_ecb(ctx, output, outputDec, textLen89)) - return -1; - - if(memcmp(outputDec, kGost89PlaintText, textLen89)) - return -1; - - free_ecb(ctx); - - return 0; -} - -/** @brief теÑтирование режима ctr алгоритма 28147-89 */ -int gost89_CTR_test() -{ - const size_t SvLen = sizeof(kGost89CtrSV); - - unsigned char outText[textLen89]; - unsigned char ctx[kCtr89ContextLen]; - - PrintLabel("Ctr mode 28147-89 test start."); - - if(init_ctr_89(kMasterKeyGost89, kGost89CtrSV, kBlockLen89, ctx, print_array, print_uint_array)) - return -1; - - if(crypt_ctr(ctx, kGost89PlaintText, outText, textLen89)) - return -1; - - free_ctr(ctx); - - PrintBlock("Master Key: ", kMasterKeyGost89, 32, kBlockLen89); - PrintEmptyLine(); - PrintBlock("SV: ", kGost89CtrSV, SvLen, kBlockLen89); - PrintEmptyLine(); - PrintBlock("Input Value: ", kGost89PlaintText, textLen89, kBlockLen89); - PrintEmptyLine(); - PrintBlock("Output Value: ", outText, textLen89, kBlockLen89); - PrintEmptyLine(); - PrintBlock("Control value: ", kGost89CtrC, textLen89, kBlockLen89); - PrintEmptyLine(); - - return memcmp(outText, kGost89CtrC, textLen89); -} - -/** @brief теÑтирование режима ofb алгоритма 28147-89 */ -int gost89_OFB_test() -{ - const size_t SvLen = sizeof(kGost89OfbSV); - - unsigned char outText[textLen89]; - unsigned char ctx[kOfb89ContextLen]; - - PrintLabel("Ofb mode 28147-89 test start."); - - if(init_ofb_89(kMasterKeyGost89, ctx, kBlockLen89, kGost89OfbSV, SvLen, print_array, print_uint_array)) - return -1; - - if(crypt_ofb(ctx, kGost89PlaintText, outText, textLen89)) - return -1; - - PrintBlock("Master Key: ", kMasterKeyGost89, 32, kBlockLen89); - PrintEmptyLine(); - PrintBlock("SV: ", kGost89OfbSV, SvLen, kBlockLen89); - PrintEmptyLine(); - PrintBlock("Input Value: ", kGost89PlaintText, textLen89, kBlockLen89); - PrintEmptyLine(); - PrintBlock("Output Value: ", outText, textLen89, kBlockLen89); - PrintEmptyLine(); - PrintBlock("Control value: ", kGost89OfbC, textLen89, kBlockLen89); - PrintEmptyLine(); - - free_ofb(ctx); - - return memcmp(outText, kGost89OfbC, textLen89); -} - -/** @brief теÑтирование режима cbc алгоритма 28147-89 */ -int gost89_CBC_test() -{ - const size_t SvLen = sizeof(kGost89CbcSV); - - unsigned char outText[textLen89]; - unsigned char outTextDec[textLen89]; - unsigned char ctx[kCbc89ContextLen]; - - PrintLabel("Cbc mode 28147-89 test start."); - - if(init_cbc_89(kMasterKeyGost89, ctx, kGost89CbcSV, SvLen, print_array, print_uint_array)) - return -1; - - if(encrypt_cbc(ctx, kGost89PlaintText, outText, textLen89)) - return 0; - - free_cbc(ctx); - - PrintBlock("Master Key: ", kMasterKeyGost89, 32, kBlockLen89); - PrintEmptyLine(); - PrintBlock("SV: ", kGost89CbcSV, SvLen, kBlockLen89); - PrintEmptyLine(); - PrintBlock("Input Value: ", kGost89PlaintText, textLen89, kBlockLen89); - PrintEmptyLine(); - PrintBlock("Output Value: ", outText, textLen89, kBlockLen89); - PrintEmptyLine(); - PrintBlock("Control value: ", kGost89CbcC, textLen89, kBlockLen89); - PrintEmptyLine(); - - if(init_cbc_89(kMasterKeyGost89, ctx, kGost89CbcSV, SvLen, print_array, print_uint_array)) - return -1; - - if(decrypt_cbc(ctx, outText, outTextDec, textLen89)) - return -1; - - free_cbc(ctx); - - if(memcmp(outTextDec, kGost89PlaintText, textLen89)) - return -1; - - return memcmp(outText, kGost89CbcC, textLen89); -} - -/** @brief ТеÑтирование криптографичеÑкого Ð¿Ñ€ÐµÐ¾Ð±Ñ€Ð°Ð·Ð¾Ð²Ð°Ð½Ð¸Ñ Ð°Ð»Ð³Ð¾Ñ€Ð¸Ñ‚Ð¼Ð° 28147-89 */ -int standart_89_encr_test() -{ - const size_t textLen = sizeof(kGost89StandartPlainText); - - unsigned char ctx[kEcb89ContextLen]; - unsigned char output[sizeof(kGost89StandartPlainText)]; - unsigned char outputE[sizeof(kGost89StandartPlainText)]; - - PrintLabel("Standart 28147-89 encryption test start."); - - if(init_ecb_89(kMasterKeyGost89, ctx, print_array, print_uint_array)) - return -1; - - if(encrypt_ecb(ctx, kGost89StandartPlainText, output, textLen)) - return -1; - - PrintBlock("Master Key: ", kMasterKeyGost89, 32, kBlockLen89); - PrintEmptyLine(); - - PrintBlock("Input Value: ", kGost89StandartPlainText, textLen, kBlockLen89); - PrintEmptyLine(); - PrintBlock("Output Value: ", output, textLen, kBlockLen89); - PrintEmptyLine(); - PrintBlock("Control value: ", kGost89StandartEncrText, textLen, kBlockLen89); - PrintEmptyLine(); - - if(memcmp(output, kGost89StandartEncrText, textLen)) - return -1; - - free_ecb(ctx); - - if(init_ecb_89(kMasterKeyGost89, ctx, print_array, print_uint_array)) - return -1; - - if(decrypt_ecb(ctx, output, outputE, textLen)) - return -1; - - if(memcmp(outputE, kGost89StandartPlainText, textLen)) - return -1; - - free_ecb(ctx); - - return 0; -} - -/** @brief теÑтирование режима cfb алгоритма 28147-89 */ -int gost89_CFB_test() -{ - const size_t SvLen = sizeof(kGost89CfbSV); - - unsigned char outText[textLen89]; - unsigned char outTextDec[textLen89]; - unsigned char ctx[kCfb89ContextLen]; - - PrintLabel("Cfb mode 28147-89 test start."); - - if(init_cfb_89(kMasterKeyGost89, ctx, kBlockLen89, kGost89CfbSV, SvLen, print_array, print_uint_array)) - return -1; - - if(encrypt_cfb(ctx, kGost89PlaintText, outText, textLen89)) - return -1; - - PrintBlock("Master Key: ", kMasterKeyGost89, 32, kBlockLen89); - PrintEmptyLine(); - PrintBlock("SV: ", kGost89CfbSV, SvLen, kBlockLen89); - PrintEmptyLine(); - PrintBlock("Input Value: ", kGost89PlaintText, textLen89, kBlockLen89); - PrintEmptyLine(); - PrintBlock("Output Value: ", outText, textLen89, kBlockLen89); - PrintEmptyLine(); - PrintBlock("Control value: ", kGost89CfbC, textLen89, kBlockLen89); - PrintEmptyLine(); - - if(memcmp(outText, kGost89CfbC, textLen89)) - return -1; - - free_cfb(ctx); - - if(init_cfb_89(kMasterKeyGost89, ctx, kBlockLen89, kGost89CfbSV, SvLen, print_array, print_uint_array)) - return -1; - - if(decrypt_cfb(ctx, outText, outTextDec, textLen89)) - return -1; - - if(memcmp(outTextDec, kGost89PlaintText, textLen89)) - return -1; - - free_cfb(ctx); - - return 0; -} -#include<stdio.h> -/** @brief теÑтирование режима имтовÑтавки алгоритма 28147-89 */ -int gost89_imita_test() -{ - const size_t imitLen = sizeof(kGost89ImitS); - - unsigned char outText[sizeof(kGost89ImitS)]; - unsigned char ctx[kImit89ContextLen]; - - PrintLabel("Imita mode 28147-89 test start."); - - if(init_imit_89(kMasterKeyGost89, kBlockLen89, ctx, print_array, print_uint_array)) - return -1; - - if(imit(ctx, kGost89PlaintText, textLen89)) - return -1; - - done_imit(ctx, outText); - - free_imit(ctx); - - PrintBlock("Master Key: ", kMasterKeyGost89, 32, kBlockLen89); - PrintEmptyLine(); - PrintBlock("Input Value: ", kGost89PlaintText, textLen89, kBlockLen89); - PrintEmptyLine(); - PrintBlock("Output Value: ", outText, imitLen, kBlockLen89); - PrintEmptyLine(); - PrintBlock("Control value: ", kGost89ImitS, imitLen, kBlockLen89); - PrintEmptyLine(); - - return memcmp(outText, kGost89ImitS, imitLen); -} - -/** @brief теÑтирование Ð´Ð¾Ð¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ ÑÐ¾Ð¾Ð±Ñ‰ÐµÐ½Ð¸Ñ */ -int testPadding() -{ - const size_t len = sizeof(kPaddingText)/sizeof(kPaddingText[0]); - const size_t len2 = sizeof(kPaddingText2)/sizeof(kPaddingText2[0]); - - padd(paddingBufferText, 1, kBlockLen14); - padd(paddingBufferText2, kBlockLen14, 2*kBlockLen14); - - PrintLineLeft("Test 1"); - PrintBlock("Input Value: ", paddingBufferText, 1, kBlockLen14); - PrintEmptyLine(); - PrintBlock("Output Value: ", paddingBufferText, kBlockLen14, kBlockLen14); - PrintEmptyLine(); - PrintBlock("Control value: ", kPaddingText, len, kBlockLen14); - PrintEmptyLine(); - -// if(memcmp(paddingBufferText, kPaddingText, len)) -// return -1; - - PrintLineLeft("Test 2"); - PrintBlock("Input Value: ", paddingBufferText2, kBlockLen14, kBlockLen14); - PrintEmptyLine(); - PrintBlock("Output Value: ", paddingBufferText2, 2*kBlockLen14, kBlockLen14); - PrintEmptyLine(); - PrintBlock("Control value: ", kPaddingText2, len2, kBlockLen14); - PrintEmptyLine(); - fflush(stdout); - -// if(memcmp(paddingBufferText2, kPaddingText2, len2)) -// return -1; - - return 0; -} - -/** @brief теÑтирование ÑнÑÑ‚Ð¸Ñ Ð´Ð¾Ð¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ ÑÐ¾Ð¾Ð±Ñ‰ÐµÐ½Ð¸Ñ */ -int testCut() -{ - size_t rLen, rLen2; - padd(paddingBufferText, 1, kBlockLen14); - padd(paddingBufferText2, kBlockLen14, 2*kBlockLen14); - - rLen = unpadd(paddingBufferText, kBlockLen14); - rLen2 = unpadd(paddingBufferText2, 2*kBlockLen14); - - PrintLabel("Cut padding test start."); - - PrintLineLeft("Test 1"); - PrintBlock("Input Value: ", paddingBufferText, kBlockLen14, kBlockLen14); - PrintEmptyLine(); - PrintBlock("Output Value: ", paddingBufferText, rLen, kBlockLen14); - PrintEmptyLine(); - PrintBlock("Control value: ", kPaddingText, 1, kBlockLen14); - PrintEmptyLine(); - - PrintLineLeft("Test 2"); - PrintBlock("Input Value: ", paddingBufferText2, 2*kBlockLen14, kBlockLen14); - PrintEmptyLine(); - PrintBlock("Output Value: ", paddingBufferText2, rLen2, kBlockLen14); - PrintEmptyLine(); - PrintBlock("Control value: ", kPaddingText2, kBlockLen14, kBlockLen14); - PrintEmptyLine(); - - if(rLen !=1 ) - return -1; - - if(rLen2 != kBlockLen14) - return -1; - - return 0; -} - -/** @brief ТеÑтирование Ð¿Ñ€ÐµÐ¾Ð±Ñ€Ð°Ð·Ð¾Ð²Ð°Ð½Ð¸Ñ t алгоритма 28147-89 */ -int testFuncT() -{ - int i; - PrintLabel("Test 28147-89 function T start."); - - for(i = 0; i < 4; ++i) - { - unsigned int ans; - ans = funcT(kTData[i], 0); - - PrintBlockLeft("Test ", i+1); - PrintBlockInt("Input value", kTData[i]); - PrintBlockInt("Ouput value", ans); - PrintBlockInt("Control value", kTData[i+1]); - PrintEmptyLine(); - - if(ans != kTData[i+1]) - return -1; - } - - return 0; -} - -/** @brief ТеÑтирование Ð¿Ñ€ÐµÐ¾Ð±Ñ€Ð°Ð·Ð¾Ð²Ð°Ð½Ð¸Ñ g алгоритма 28147-89 */ -int testG() -{ - int i; - PrintLabel("Test 28147-89 function G start."); - - for(i = 0; i < 4; ++i) - { - unsigned int ans; - ans = funcG(kgData[i][0], kgData[i][1], 0); - - PrintBlockLeft("Test ", i+1); - PrintBlockInt("Input value", kgData[i][0]); - PrintBlockInt("Key value", kgData[i][1]); - PrintBlockInt("Ouput value", ans); - PrintBlockInt("Control value", kgData[i][2]); - PrintEmptyLine(); - - if( ans!= kgData[i][2]) - return -1; - } - - return 0; -} - -/** @brief точка входа */ -int main_gost_test() -{ - int testRes = 0; - PrintLine("TEST start."); - PrintEmptyLine(); - - PrintLine("TEST 28147-14 standart start."); - testRes |= PrintTest("S function test end", testS()); - testRes |= PrintTest("R function test.", testR()); - testRes |= PrintTest("L function test.", testL()); - testRes |= PrintTest("Expand Key 28147-14 test.", testExpandKey()); - testRes |= PrintTest("Encrypt test.", testEncrypt()); - testRes |= PrintTest("Decrypt test.", testDecrypt()); - PrintEmptyLine(); - - PrintLine("TEST 28147-89 standart test."); - testRes |= PrintTest("28147-89 T function test.", testFuncT()); - testRes |= PrintTest("28147-89 G function test.", testG()); - testRes |= PrintTest("Encrypt test.", standart_89_encr_test()); - PrintEmptyLine(); - - PrintLine("TEST 28147-14 mode test."); - testRes |= PrintTest("Ecb mode 28147-14 test.", gost14_ECB_test()); - testRes |= PrintTest("CTR mode 28147-14 test.", gost14_CTR_test()); - testRes |= PrintTest("OFB mode 28147-14 test.", gost14_OFB_test()); - testRes |= PrintTest("CBC mode 28147-14 test.", gost14_CBC_test()); - testRes |= PrintTest("CFB mode 28147-14 test.", gost14_CFB_test()); - testRes |= PrintTest("Imita mode 28147-14 test.", gost14_imita_test()); - PrintEmptyLine(); - - PrintLine("TEST 28147-89 mode test."); - testRes |= PrintTest("Ecb mode 28147-89 test.", gost89_ECB_test()); - testRes |= PrintTest("CTR mode 28147-89 test.", gost89_CTR_test()); - testRes |= PrintTest("OFB mode 28147-89 test.", gost89_OFB_test()); - testRes |= PrintTest("CBC mode 28147-89 test.", gost89_CBC_test()); - testRes |= PrintTest("CFB mode 28147-89 test.", gost89_CFB_test()); - testRes |= PrintTest("Imita mode 28147-89 test.", gost89_imita_test()); - PrintEmptyLine(); - - PrintLine("TEST padding test."); - - testRes |= PrintTest("Add padding test.", testPadding()); - testRes |= PrintTest("Cut padding test.", testCut()); - PrintEmptyLine(); - - if ( testRes ) - { - PrintLine("FAILED TESTS EXIST!!!!!."); - } - else - { - PrintLine("ALL TEST OK."); - } - - return testRes; -} diff --git a/dap-sdk/crypto/src/rand/dap_rand.c b/dap-sdk/crypto/src/rand/dap_rand.c index 7a2c48e3a6c787e858c3fbde3d87f406c387f974..4e102fd6621a6f20d858866b89e504ceb746ae8d 100755 --- a/dap-sdk/crypto/src/rand/dap_rand.c +++ b/dap-sdk/crypto/src/rand/dap_rand.c @@ -29,7 +29,7 @@ uint32_t random_uint32_t(const uint32_t MAX_NUMBER) int randombase64(void*random_array, unsigned int size) { int off = size - (size/4)*3; - int odd_signs = size - ((size/4)*4); + unsigned int odd_signs = size - ((size/4)*4); if(odd_signs < size) { randombytes(random_array + off, (size/4)*3); @@ -39,8 +39,8 @@ int randombase64(void*random_array, unsigned int size) { uint8_t tmpv[7]; randombytes(tmpv+4,3); - dap_enc_base64_encode(tmpv + 4, 3,tmpv,DAP_ENC_DATA_TYPE_B64); - for(int i = 0; i < odd_signs; ++i) + dap_enc_base64_encode(tmpv + 4, 3,(char*)tmpv,DAP_ENC_DATA_TYPE_B64); + for(unsigned int i = 0; i < odd_signs; ++i) { ((uint8_t*)random_array)[size - odd_signs + i] = tmpv[i]; } diff --git a/dap-sdk/crypto/src/ringct20/poly.c b/dap-sdk/crypto/src/ringct20/poly.c index ed350c619ddbff01cbcc30892d2bdb58ec3aa6ec..f00896fa7674fafe494c2ca1cc05e617ec3f66e3 100644 --- a/dap-sdk/crypto/src/ringct20/poly.c +++ b/dap-sdk/crypto/src/ringct20/poly.c @@ -427,7 +427,7 @@ void poly_serial(poly_ringct20 *r) r->coeffs[i] = coeff_freeze(r->coeffs[i]); } } -void poly_cofcopy(poly_ringct20 *des, poly_ringct20 *sour) +void poly_cofcopy(poly_ringct20 *des, const poly_ringct20 *sour) { size_t i; for ( i = 0; i < NEWHOPE_RINGCT20_N; i++) @@ -436,18 +436,16 @@ void poly_cofcopy(poly_ringct20 *des, poly_ringct20 *sour) } } -void poly_copy(poly_ringct20 *des, poly_ringct20 *sou, size_t mLen) +void poly_copy(poly_ringct20 *des, const poly_ringct20 *sou, const int mLen) { - size_t i; - for ( i = 0; i < mLen; i++) + for (int i = 0; i < mLen; i++) { poly_cofcopy(des + i, sou + i); } } int poly_equal(const poly_ringct20 *a, const poly_ringct20 *b) { - size_t i; - for ( i = 0; i < NEWHOPE_RINGCT20_N; i++) + for (int i = 0; i < NEWHOPE_RINGCT20_N; i++) { if (a->coeffs[i] != b->coeffs[i]) { @@ -459,9 +457,8 @@ int poly_equal(const poly_ringct20 *a, const poly_ringct20 *b) void poly_constmul(poly_ringct20 *r, const poly_ringct20 *a, uint16_t cof) { - size_t i; uint32_t tmp = 0; - for (i = 0; i < NEWHOPE_RINGCT20_N; i++) + for (int i = 0; i < NEWHOPE_RINGCT20_N; i++) { tmp = cof * a->coeffs[i]; r->coeffs[i] = tmp%NEWHOPE_RINGCT20_2Q; diff --git a/dap-sdk/crypto/src/ringct20/poly.h b/dap-sdk/crypto/src/ringct20/poly.h index 78894205666f6bf34f20ef088bb7444ee302ab91..c05658f14f508352453036aa109e10e2e5dd02ac 100644 --- a/dap-sdk/crypto/src/ringct20/poly.h +++ b/dap-sdk/crypto/src/ringct20/poly.h @@ -45,7 +45,7 @@ int poly_equal(const poly_ringct20 *a, const poly_ringct20 *b); // void poly_constmul(poly_ringct20 *r, const poly_ringct20 *a, uint16_t cof); void poly_serial(poly_ringct20 *r); -void poly_cofcopy(poly_ringct20 *des, poly_ringct20 *sour); -void poly_copy(poly_ringct20 *des, poly_ringct20 *sour, size_t mLen); +void poly_cofcopy(poly_ringct20 *des, const poly_ringct20 *sour); +void poly_copy(poly_ringct20 *des, const poly_ringct20 *sour, const int mLen); void poly_shift(poly_ringct20 *des, const poly_ringct20 *r, int iNumber); #endif diff --git a/dap-sdk/crypto/src/ringct20/ring.c b/dap-sdk/crypto/src/ringct20/ring.c index ca36f6dfdb059169ced2222e99fa6b462a33ddeb..e85b12ebecfad7d9770ee71d415a988a1035cef9 100644 --- a/dap-sdk/crypto/src/ringct20/ring.c +++ b/dap-sdk/crypto/src/ringct20/ring.c @@ -5,10 +5,10 @@ #define Keccak_HashInitialize_SHA3_KDF(hashInstance, out_bytes) Keccak_HashInitialize(hashInstance, 1088, 512, out_bytes*8, 0x06) -void LRCT_SampleKey(poly_ringct20 *r, size_t mLen) +void LRCT_SampleKey(poly_ringct20 *r, int mLen) { uint8_t seed[NEWHOPE_RINGCT20_SYMBYTES] = { 0 }; - size_t i; + int i; for ( i = 0; i < mLen; i++) { #ifndef NEW_SAMPLE_KEY @@ -57,11 +57,11 @@ void LRCT_SampleKey(poly_ringct20 *r, size_t mLen) } } -void LRCT_Setup(poly_ringct20 *A, poly_ringct20 *H, size_t mLen) +void LRCT_Setup(poly_ringct20 *A, poly_ringct20 *H, int mLen) { uint8_t seed[NEWHOPE_RINGCT20_SYMBYTES] = { 0 }; - size_t i = 0; + int i = 0; for ( i = 0; i < mLen; i++) { @@ -74,16 +74,18 @@ void LRCT_Setup(poly_ringct20 *A, poly_ringct20 *H, size_t mLen) } } -void LRCT_KeyGen(poly_ringct20 *a, poly_ringct20 *A, poly_ringct20 *S, size_t mLen) +void LRCT_KeyGen(poly_ringct20 *a, poly_ringct20 *A, poly_ringct20 *S, int mLen) { LRCT_MatrixMulPoly(a, A, S, mLen); poly_serial(a); } -void LRCT_SigGen(poly_ringct20 *c1, poly_ringct20 **t, poly_ringct20 *h, poly_ringct20 *A, poly_ringct20 *H, poly_ringct20 *S, poly_ringct20 *u, size_t mLen, poly_ringct20 *L, uint8_t w, uint8_t pai, const unsigned char *msg, int msgLen) +void LRCT_SigGen(poly_ringct20 *c1, poly_ringct20 **t, poly_ringct20 *h, + poly_ringct20 *A, poly_ringct20 *H, poly_ringct20 *S, poly_ringct20 *u, + int mLen, poly_ringct20 *L, int w, int pai, const unsigned char *msg, int msgLen) { //H2q - size_t i, j, k; + int i, j, k; poly_ringct20 *H2q = (poly_ringct20 *)malloc((mLen + 1) * sizeof(poly_ringct20)); poly_ringct20 *S2q = (poly_ringct20 *)malloc((mLen + 1) * sizeof(poly_ringct20)); poly_ringct20 *A2qp = (poly_ringct20 *)malloc((mLen + 1) * sizeof(poly_ringct20)); @@ -93,7 +95,7 @@ void LRCT_SigGen(poly_ringct20 *c1, poly_ringct20 **t, poly_ringct20 *h, poly_ri //SHA256_CTX ctx; Keccak_HashInstance ctx; - unsigned char bHash[32] = { 0 }; +// unsigned char bHash[32] = { 0 }; unsigned char bpoly[NEWHOPE_RINGCT20_POLYBYTES] = { 0 }; unsigned char bt[NEWHOPE_RINGCT20_POLYBYTES] = { 0 }; uint8_t coin = 0; @@ -232,16 +234,16 @@ void LRCT_SigGen(poly_ringct20 *c1, poly_ringct20 **t, poly_ringct20 *h, poly_ri free(A2qp); free(tmp2q); } -int LRCT_SigVer(const poly_ringct20 *c1, poly_ringct20 **t, poly_ringct20 *A, poly_ringct20 *H, size_t mLen, poly_ringct20 *h, poly_ringct20 *L, - uint8_t w, const unsigned char *msg, int msgLen) +int LRCT_SigVer(const poly_ringct20 *c1, poly_ringct20 **t, poly_ringct20 *A, poly_ringct20 *H, int mLen, poly_ringct20 *h, poly_ringct20 *L, + int w, const unsigned char *msg, int msgLen) { - size_t i,k; + int i,k; poly_ringct20 *H2q = (poly_ringct20 *)malloc((mLen + 1) * sizeof(poly_ringct20)); poly_ringct20 *A2qp = (poly_ringct20 *)malloc((mLen + 1) * sizeof(poly_ringct20)); poly_ringct20 c, tmp, tmp1; //SHA256_CTX ctx; Keccak_HashInstance ctx; - unsigned char bHash[32] = { 0 }; +// unsigned char bHash[32] = { 0 }; unsigned char bpoly[NEWHOPE_RINGCT20_POLYBYTES] = { 0 }; for (i = 0; i < (mLen + 1); i++) { @@ -307,14 +309,14 @@ int LRCT_SigVer(const poly_ringct20 *c1, poly_ringct20 **t, poly_ringct20 *A, po return 0; } -void LRCT_Mint(IW *iw, poly_ringct20 *ck, poly_ringct20 *a, poly_ringct20 *A, size_t mLen, unsigned char* bMessage, size_t msglen) +void LRCT_Mint(IW *iw, poly_ringct20 *ck, poly_ringct20 *a, poly_ringct20 *A, int mLen, unsigned char* bMessage, size_t msglen) { LRCT_SampleKey(ck, mLen); LRCT_nttCom(&(iw->cn), A, ck, mLen, bMessage, msglen); poly_cofcopy(&(iw->a), a); } void LRCT_Spend(IW *iwOA, poly_ringct20 *ckOA, poly_ringct20 *c1, poly_ringct20 **t, poly_ringct20 *h, poly_ringct20 *L, unsigned char* bSignMess, size_t sigMsgLen, IW *iws, size_t iwsLen, - int PaiInd, poly_ringct20 *skPai, poly_ringct20 *ckPai, unsigned char* bVal, size_t bvalLen, poly_ringct20 *OA, poly_ringct20 *A, poly_ringct20 *H, size_t mLen) + int PaiInd, poly_ringct20 *skPai, poly_ringct20 *ckPai, unsigned char* bVal, size_t bvalLen, poly_ringct20 *OA, poly_ringct20 *A, poly_ringct20 *H, int mLen) { poly_ringct20 *u = (poly_ringct20 *)malloc((mLen+1)*sizeof(poly_ringct20)); @@ -336,18 +338,18 @@ void LRCT_Spend(IW *iwOA, poly_ringct20 *ckOA, poly_ringct20 *c1, poly_ringct20 free(u); free(S); } -int LRCT_Verify(poly_ringct20 *c1, poly_ringct20 **t, poly_ringct20 *h, poly_ringct20* A, poly_ringct20 *H, size_t mLen, - unsigned char* bSignMess, size_t sigMsgLen, poly_ringct20 *L, size_t iwsLen) +int LRCT_Verify(poly_ringct20 *c1, poly_ringct20 **t, poly_ringct20 *h, poly_ringct20* A, poly_ringct20 *H, int mLen, + unsigned char* bSignMess, size_t sigMsgLen, poly_ringct20 *L, int iwsLen) { int result = 0; result = LRCT_SigVer(c1, t, A, H, mLen, h, L, iwsLen, bSignMess, sigMsgLen); return result; } /////multiple -void MIMO_LRCT_Setup(poly_ringct20 *A, poly_ringct20 *H, size_t mLen) +void MIMO_LRCT_Setup(poly_ringct20 *A, poly_ringct20 *H, int mLen) { uint8_t seed[NEWHOPE_RINGCT20_SYMBYTES] = { 0 }; - size_t i = 0; + int i = 0; for (i = 0; i < mLen; i++) { @@ -359,23 +361,23 @@ void MIMO_LRCT_Setup(poly_ringct20 *A, poly_ringct20 *H, size_t mLen) poly_serial(H + i); } } -void MIMO_LRCT_KeyGen(poly_ringct20 *a, poly_ringct20 *A, poly_ringct20 *S, size_t mLen) +void MIMO_LRCT_KeyGen(poly_ringct20 *a, poly_ringct20 *A, poly_ringct20 *S, int mLen) { LRCT_MatrixMulPoly(a, A, S, mLen); poly_serial(a); } -void MIMO_LRCT_Mint(IW *iw, poly_ringct20 *ck, poly_ringct20 *a, poly_ringct20 *A, size_t mLen, unsigned char* bMessage, size_t msglen) +void MIMO_LRCT_Mint(IW *iw, poly_ringct20 *ck, poly_ringct20 *a, poly_ringct20 *A, int mLen, unsigned char* bMessage, size_t msglen) { LRCT_SampleKey(ck, mLen); LRCT_nttCom(&(iw->cn), A, ck, mLen, bMessage, msglen); poly_cofcopy(&(iw->a), a); } -void MIMO_LRCT_Hash(int *pTable, poly_ringct20 *cn, poly_ringct20 *a, poly_ringct20 *ia, int beta) +void MIMO_LRCT_Hash(/*int *pTable, */poly_ringct20 *cn, poly_ringct20 *a, poly_ringct20 *ia, int beta) { //SHA256_CTX ctx; Keccak_HashInstance ctx; - unsigned char bHash[32] = { 0 }; +// unsigned char bHash[32] = { 0 }; unsigned char bpoly[NEWHOPE_RINGCT20_POLYBYTES] = { 0 }; unsigned char bt[NEWHOPE_RINGCT20_POLYCOMPRESSEDBYTES] = { 0 }; int i; @@ -402,8 +404,8 @@ void MIMO_LRCT_Hash(int *pTable, poly_ringct20 *cn, poly_ringct20 *a, poly_ringc } //// -void ZKP_OR(poly_ringct20 *ck, int bit, int betaLen) -{} +//void ZKP_OR(poly_ringct20 *ck, int bit, int betaLen) +//{} ////// void MIMO_LRCT_SigGen(poly_ringct20 *c1, poly_ringct20 *tList, poly_ringct20 *hList, poly_ringct20 *SList, int NLen, poly_ringct20 *A, poly_ringct20 *H, int mLen, poly_ringct20 *LList, int wLen, uint8_t pai, unsigned char *msg, int msgLen) @@ -419,7 +421,7 @@ void MIMO_LRCT_SigGen(poly_ringct20 *c1, poly_ringct20 *tList, poly_ringct20 *hL poly_ringct20 tmp, tmp1, ctmp; poly_ringct20 c, cpai; - unsigned char bHash[32] = { 0 }; +// unsigned char bHash[32] = { 0 }; unsigned char bpoly[NEWHOPE_RINGCT20_POLYBYTES] = { 0 }; unsigned char bt[NEWHOPE_RINGCT20_POLYBYTES] = { 0 }; uint8_t coin = 0; @@ -571,17 +573,17 @@ void MIMO_LRCT_SigGen(poly_ringct20 *c1, poly_ringct20 *tList, poly_ringct20 *hL } -int MIMO_LRCT_SigVer(poly_ringct20 *c1, poly_ringct20 *tList, poly_ringct20 *hList, int NLen, poly_ringct20 *A, poly_ringct20 *H, - size_t mLen, poly_ringct20 *LList, int wLen, unsigned char *msg, int msgLen) +int MIMO_LRCT_SigVer(poly_ringct20 *c1, poly_ringct20 *tList, poly_ringct20 *hList, int NLen, poly_ringct20 *A,/* poly_ringct20 *H,*/ + int mLen, poly_ringct20 *LList, int wLen, unsigned char *msg, int msgLen) { - size_t i,j, k; + int i,j, k; poly_ringct20 *H2q = (poly_ringct20 *)malloc(NLen*(mLen + 1) * sizeof(poly_ringct20)); poly_ringct20 *A2qp = (poly_ringct20 *)malloc((mLen + 1) * sizeof(poly_ringct20)); poly_ringct20 ctmp,tmp, tmp1; //SHA256_CTX ctx; Keccak_HashInstance ctx; - unsigned char bHash[32] = { 0 }; +// unsigned char bHash[32] = { 0 }; unsigned char bpoly[NEWHOPE_RINGCT20_POLYBYTES] = { 0 }; ///////// poly_cofcopy(&ctmp, c1); @@ -639,11 +641,10 @@ int MIMO_LRCT_SigVer(poly_ringct20 *c1, poly_ringct20 *tList, poly_ringct20 *hLi -void LRCT_Lift(poly_ringct20 *LA, poly_ringct20 *A, poly_ringct20 *a, size_t mLen) +void LRCT_Lift(poly_ringct20 *LA, poly_ringct20 *A, poly_ringct20 *a, int mLen) { - size_t i = 0; - size_t j = 0; - int16_t tmp = 0; + int i = 0; + int j = 0; for ( i = 0; i < mLen; i++) { for ( j = 0; j < NEWHOPE_RINGCT20_N; j++) @@ -657,10 +658,10 @@ void LRCT_Lift(poly_ringct20 *LA, poly_ringct20 *A, poly_ringct20 *a, size_t mLe } } -void LRCT_Com(poly_ringct20 *r, poly_ringct20 *A, poly_ringct20 *sk, size_t mLen, unsigned char *bMessage, size_t msglen) +void LRCT_Com(poly_ringct20 *r, poly_ringct20 *A, poly_ringct20 *sk, int mLen, unsigned char *bMessage, size_t msglen) { poly_ringct20 tmp; - size_t j; + size_t j; LRCT_MatrixMulPoly(&tmp, A, sk, mLen); poly_cofcopy(r, &tmp); @@ -678,7 +679,7 @@ void LRCT_Com(poly_ringct20 *r, poly_ringct20 *A, poly_ringct20 *sk, size_t mLen } } -void LRCT_nttCom(poly_ringct20 *r, poly_ringct20 *A, poly_ringct20 *sk, size_t mLen, unsigned char *bMessage, size_t msglen) +void LRCT_nttCom(poly_ringct20 *r, poly_ringct20 *A, poly_ringct20 *sk, int mLen, unsigned char *bMessage, size_t msglen) { poly_ringct20 tmp, pMess; size_t j; @@ -704,9 +705,9 @@ void LRCT_nttCom(poly_ringct20 *r, poly_ringct20 *A, poly_ringct20 *sk, size_t m //N*M mul M*1 -void LRCT_MatrixMulPoly(poly_ringct20 *r, poly_ringct20 *A, poly_ringct20 *s, size_t mLen) +void LRCT_MatrixMulPoly(poly_ringct20 *r, poly_ringct20 *A, poly_ringct20 *s, int mLen) { - size_t i; + int i; poly_ringct20 tmp, tmpA, tmps; poly_init(r); for ( i = 0; i < mLen; i++) @@ -721,35 +722,32 @@ void LRCT_MatrixMulPoly(poly_ringct20 *r, poly_ringct20 *A, poly_ringct20 *s, si //poly_invntt(r); } //M*N mul N*1 -void LRCT_PolyMultMatrix(poly_ringct20 *r, poly_ringct20 *p, poly_ringct20 *A, size_t mLen) +void LRCT_PolyMultMatrix(poly_ringct20 *r, poly_ringct20 *p, poly_ringct20 *A, int mLen) { - size_t i; - for ( i = 0; i < mLen; i++) + for (int i = 0; i < mLen; i++) { poly_mul_pointwise(r+i, A+i, p); } } -void LRCT_MatrixAddMatrix(poly_ringct20 *R, poly_ringct20 *A, poly_ringct20 *B, size_t mLen) +void LRCT_MatrixAddMatrix(poly_ringct20 *R, poly_ringct20 *A, poly_ringct20 *B, int mLen) { - size_t i; - for ( i = 0; i < mLen; i++) + for (int i = 0; i < mLen; i++) { poly_add_ringct20(R + i, A + i, B + i); } } -void LRCT_MatrixSubMatrix(poly_ringct20 *R, poly_ringct20 *A, poly_ringct20 *B, size_t mLen) +void LRCT_MatrixSubMatrix(poly_ringct20 *R, poly_ringct20 *A, poly_ringct20 *B, int mLen) { - size_t i; - for (i = 0; i < mLen; i++) + for (int i = 0; i < mLen; i++) { poly_sub_ringct20(R + i, A + i, B + i); } } -void LRCT_ConstMulMatrix(poly_ringct20 *r, const poly_ringct20 *A, uint16_t cof, size_t mLen) +void LRCT_ConstMulMatrix(poly_ringct20 *r, const poly_ringct20 *A, uint16_t cof, int mLen) { - size_t i, j; + int i, j; for (i = 0; i < mLen; i++) { for ( j = 0; j < NEWHOPE_RINGCT20_N; j++) @@ -760,18 +758,17 @@ void LRCT_ConstMulMatrix(poly_ringct20 *r, const poly_ringct20 *A, uint16_t cof, } } /// -void LRCT_MatrixShift(poly_ringct20 *desCK, poly_ringct20* rCK, size_t mLen, int iNumber) +void LRCT_MatrixShift(poly_ringct20 *desCK, poly_ringct20* rCK, int mLen, int iNumber) { - size_t i; - for ( i = 0; i < mLen; i++) + for (int i = 0; i < mLen; i++) { poly_shift(desCK + i, rCK + i, iNumber); } } -void LRCT_GetCK0(poly_ringct20 *CK0, poly_ringct20 * CK, size_t mLen, poly_ringct20* CKi, int messBitLen) +void LRCT_GetCK0(poly_ringct20 *CK0, poly_ringct20 * CK, int mLen, poly_ringct20* CKi, int messBitLen) { - size_t i; + int i; poly_ringct20 *tmp = (poly_ringct20 *)malloc((mLen) * sizeof(poly_ringct20)); poly_ringct20 *desCK = (poly_ringct20 *)malloc((mLen) * sizeof(poly_ringct20)); for (i = 0; i < (mLen); i++) diff --git a/dap-sdk/crypto/src/ringct20/ring.h b/dap-sdk/crypto/src/ringct20/ring.h index 63c94d7dce4b112ad4bfcb4eaa2dbf87ac7429ef..1d23baec753fd7f84dd0b13bb9a8d87d9d15d536 100644 --- a/dap-sdk/crypto/src/ringct20/ring.h +++ b/dap-sdk/crypto/src/ringct20/ring.h @@ -15,22 +15,22 @@ typedef struct { poly_ringct20 cn; } IW; -void LRCT_Setup(poly_ringct20 *A, poly_ringct20 *H, size_t mLen); -void LRCT_KeyGen(poly_ringct20 *a, poly_ringct20 *A, poly_ringct20 *S, size_t mLen); +void LRCT_Setup(poly_ringct20 *A, poly_ringct20 *H, int mLen); +void LRCT_KeyGen(poly_ringct20 *a, poly_ringct20 *A, poly_ringct20 *S, int mLen); void LRCT_SigGen(poly_ringct20 *c1, poly_ringct20 **t, poly_ringct20 *h, poly_ringct20 *A, poly_ringct20 *H, - poly_ringct20 *S, poly_ringct20 *u, size_t mLen, poly_ringct20 *L, uint8_t w, - uint8_t pai, const unsigned char *msg, int msgLen); -int LRCT_SigVer(const poly_ringct20 *c1, poly_ringct20 **t, poly_ringct20 *A, poly_ringct20 *H, size_t mLen, poly_ringct20 *h, poly_ringct20 *L, - uint8_t w, const unsigned char *msg, int msgLen); + poly_ringct20 *S, poly_ringct20 *u, int mLen, poly_ringct20 *L, int w, + int pai, const unsigned char *msg, int msgLen); +int LRCT_SigVer(const poly_ringct20 *c1, poly_ringct20 **t, poly_ringct20 *A, poly_ringct20 *H, int mLen, poly_ringct20 *h, poly_ringct20 *L, + int w, const unsigned char *msg, int msgLen); /////Single output trading scheme /* plan description: */ -void LRCT_Mint(IW *iw, poly_ringct20 *ck, poly_ringct20 *a, poly_ringct20 *A, size_t mLen, unsigned char* bMessage, size_t msglen); +void LRCT_Mint(IW *iw, poly_ringct20 *ck, poly_ringct20 *a, poly_ringct20 *A, int mLen, unsigned char* bMessage, size_t msglen); void LRCT_Spend(IW *iwOA, poly_ringct20 *ckOA, poly_ringct20 *c1, poly_ringct20 **t, poly_ringct20 *h, poly_ringct20 *L, unsigned char* bSignMess, size_t sigMsgLen, IW *iws, size_t iwsLen, - int PaiInd, poly_ringct20 *skPai, poly_ringct20 *ckPai, unsigned char* bVal, size_t bvalLen, poly_ringct20 *OA, poly_ringct20 *A, poly_ringct20 *H, size_t mLen); -int LRCT_Verify(poly_ringct20 *c1, poly_ringct20 **t, poly_ringct20 *h, poly_ringct20* A, poly_ringct20 *H, size_t mLen, - unsigned char* bSignMess, size_t sigMsgLen, poly_ringct20 *L, size_t iwsLen); + int PaiInd, poly_ringct20 *skPai, poly_ringct20 *ckPai, unsigned char* bVal, size_t bvalLen, poly_ringct20 *OA, poly_ringct20 *A, poly_ringct20 *H, int mLen); +int LRCT_Verify(poly_ringct20 *c1, poly_ringct20 **t, poly_ringct20 *h, poly_ringct20* A, poly_ringct20 *H, int mLen, + unsigned char* bSignMess, size_t sigMsgLen, poly_ringct20 *L, int iwsLen); // /* @@ -41,13 +41,13 @@ MIMO SCheme Function declaration: system initialization, generating public parameters Output: public matrix A, H, row number mLen */ -void MIMO_LRCT_Setup(poly_ringct20 *A, poly_ringct20 *H, size_t mLen); +void MIMO_LRCT_Setup(poly_ringct20 *A, poly_ringct20 *H, int mLen); /* Function declaration: key generation. Input: matrix A, private key S, matrix row number mLen Output: user public key */ -void MIMO_LRCT_KeyGen(poly_ringct20 *a, poly_ringct20 *A, poly_ringct20 *S, size_t mLen); +void MIMO_LRCT_KeyGen(poly_ringct20 *a, poly_ringct20 *A, poly_ringct20 *S, int mLen); /* Function declaration: signature generation Input: private key list SList, length NLen, public parameters A, H, matrix width mLen, public key list LList, length wLen, trader position pai, signature message msg, message length msgLen @@ -59,58 +59,58 @@ void MIMO_LRCT_SigGen(poly_ringct20 *c1, poly_ringct20 *tList, poly_ringct20 *hL Function declaration: signature verification Input: signature (c1, t-list tList, h-list: hList, number of transactions, public parameters A, H, matrix width mLen, public key list LList, list length wLen, signature message, message length) */ -int MIMO_LRCT_SigVer(poly_ringct20 *c1, poly_ringct20 *tList, poly_ringct20 *hList, int NLen, poly_ringct20 *A, poly_ringct20 *H, - size_t mLen, poly_ringct20 *LList, int wLen, unsigned char *msg, int msgLen); +int MIMO_LRCT_SigVer(poly_ringct20 *c1, poly_ringct20 *tList, poly_ringct20 *hList, int NLen, poly_ringct20 *A, /*poly_ringct20 *H,*/ + int mLen, poly_ringct20 *LList, int wLen, unsigned char *msg, int msgLen); /* */ -void MIMO_LRCT_Mint(IW *iw, poly_ringct20 *ck, poly_ringct20 *a, poly_ringct20 *A, size_t mLen, unsigned char* bMessage, size_t msglen); +void MIMO_LRCT_Mint(IW *iw, poly_ringct20 *ck, poly_ringct20 *a, poly_ringct20 *A, int mLen, unsigned char* bMessage, size_t msglen); /// -void MIMO_LRCT_Hash(int *pTable, poly_ringct20 *cn, poly_ringct20 *a, poly_ringct20 *ia, int beta); +void MIMO_LRCT_Hash(/*int *pTable, */poly_ringct20 *cn, poly_ringct20 *a, poly_ringct20 *ia, int beta); ////// void ZKP_OR(poly_ringct20 *ck , int bit, int betaLen); //////////// -void LRCT_Lift(poly_ringct20 *LA, poly_ringct20 *A, poly_ringct20 *a, size_t mLen); +void LRCT_Lift(poly_ringct20 *LA, poly_ringct20 *A, poly_ringct20 *a, int mLen); /* Function declaration: promise message m, r = A * sk + m Input: public matrix A, private key sk, matrix row number mLen, acknowledge message m, message length bMessage Output: Commitment r (polynomial N * 1) */ -void LRCT_Com(poly_ringct20 *r, poly_ringct20 *A, poly_ringct20 *sk, size_t mLen, unsigned char *bMessage, size_t msglen); -void LRCT_nttCom(poly_ringct20 *r, poly_ringct20 *A, poly_ringct20 *sk, size_t mLen, unsigned char *bMessage, size_t msglen); +void LRCT_Com(poly_ringct20 *r, poly_ringct20 *A, poly_ringct20 *sk, int mLen, unsigned char *bMessage, size_t msglen); +void LRCT_nttCom(poly_ringct20 *r, poly_ringct20 *A, poly_ringct20 *sk, int mLen, unsigned char *bMessage, size_t msglen); /* Function declaration: matrix A (N * M) * matrix s (M * 1) Input: matrix A, matrix s, matrix rows mLen Output: matrix r = A * s (N * 1) */ -void LRCT_MatrixMulPoly(poly_ringct20 *r, poly_ringct20 *A, poly_ringct20 *s, size_t mLen); +void LRCT_MatrixMulPoly(poly_ringct20 *r, poly_ringct20 *A, poly_ringct20 *s, int mLen); /* Function declaration: constant * matrix Input: constant cof, matrix A, number of matrix rows (mLen) Output: matrix r */ -void LRCT_ConstMulMatrix(poly_ringct20 *r, const poly_ringct20 *A, uint16_t cof, size_t mLen); +void LRCT_ConstMulMatrix(poly_ringct20 *r, const poly_ringct20 *A, uint16_t cof, int mLen); /* Function declaration: matrix A (M rows and N columns) * polynomial p (N rows and 1 column) Input: polynomial p, matrix A, matrix rows mLen Output: polynomial r (M rows and 1 column) */ -void LRCT_PolyMultMatrix(poly_ringct20 *r, poly_ringct20 *p, poly_ringct20 *A, size_t mLen); +void LRCT_PolyMultMatrix(poly_ringct20 *r, poly_ringct20 *p, poly_ringct20 *A, int mLen); /* Function declaration: matrix addition (A + B) Input: matrix A, matrix B, matrix size mLen Output: Matrix R = (A + B) */ -void LRCT_MatrixAddMatrix(poly_ringct20 *R, poly_ringct20 *A, poly_ringct20 *B, size_t mLen); +void LRCT_MatrixAddMatrix(poly_ringct20 *R, poly_ringct20 *A, poly_ringct20 *B, int mLen); /* Function declaration: Matrix subtraction (A-B) Input: matrix A, matrix B, matrix size mLen Output: Matrix R = (A-B) */ -void LRCT_MatrixSubMatrix(poly_ringct20 *R, poly_ringct20 *A, poly_ringct20 *B, size_t mLen); +void LRCT_MatrixSubMatrix(poly_ringct20 *R, poly_ringct20 *A, poly_ringct20 *B, int mLen); ///////////////////* /* @@ -119,10 +119,10 @@ Input: Key length mLen Output: polynomial matrix r (n * mLen) */ ///////////////// -void LRCT_SampleKey(poly_ringct20 *r, size_t mLen); +void LRCT_SampleKey(poly_ringct20 *r, int mLen); -void LRCT_MatrixShift(poly_ringct20 *desCK, poly_ringct20* rCK, size_t mLen, int iNumber); +void LRCT_MatrixShift(poly_ringct20 *desCK, poly_ringct20* rCK, int mLen, int iNumber); -void LRCT_GetCK0(poly_ringct20 *CK0, poly_ringct20 * CK, size_t mLen, poly_ringct20* CKi, int messBitLen); +void LRCT_GetCK0(poly_ringct20 *CK0, poly_ringct20 * CK, int mLen, poly_ringct20* CKi, int messBitLen); #endif diff --git a/dap-sdk/net/client/dap_client_http.c b/dap-sdk/net/client/dap_client_http.c index e5f1ae6bb283e48bb3d7c53d509820bb3caf8cfc..b6dde60076c03551b65b453b773240ca2a368c37 100644 --- a/dap-sdk/net/client/dap_client_http.c +++ b/dap-sdk/net/client/dap_client_http.c @@ -33,6 +33,7 @@ //#include <bits/socket_type.h> #endif #include <unistd.h> +#include <errno.h> #include "dap_common.h" #include "dap_strfuncs.h" @@ -258,6 +259,52 @@ static void s_http_delete(dap_events_socket_t *a_es, void *arg) a_es->_inheritor = NULL; } +/** + * @brief resolve_host + * @param a_host hostname + * @param ai_family AF_INET for ipv4 or AF_INET6 for ipv6 + * @param a_addr_out out addr (struct in_addr or struct in6_addr) + * @param return 0 of OK, <0 Error + */ +int resolve_host(const char *a_host, int ai_family, struct sockaddr *a_addr_out) +{ + struct addrinfo l_hints, *l_res; + void *l_cur_addr = NULL; + + memset(&l_hints, 0, sizeof(l_hints)); + l_hints.ai_family = PF_UNSPEC; + l_hints.ai_socktype = SOCK_STREAM; + l_hints.ai_flags |= AI_CANONNAME; + + int errcode = getaddrinfo(a_host, NULL, &l_hints, &l_res); + if(errcode != 0) + { + return -2; + } + while(l_res) + { + if(ai_family == l_res->ai_family) + switch (l_res->ai_family) + { + case AF_INET: + l_cur_addr = &((struct sockaddr_in *) l_res->ai_addr)->sin_addr; + memcpy(a_addr_out, l_cur_addr, sizeof(struct in_addr)); + break; + case AF_INET6: + l_cur_addr = &((struct sockaddr_in6 *) l_res->ai_addr)->sin6_addr; + memcpy(a_addr_out, l_cur_addr, sizeof(struct in6_addr)); + break; + } + if(l_cur_addr) { + freeaddrinfo(l_res); + return 0; + } + l_res = l_res->ai_next; + } + freeaddrinfo(l_res); + return -1; +} + /** * @brief dap_client_http_request_custom * @param a_uplink_addr @@ -309,35 +356,37 @@ void* dap_client_http_request_custom(const char *a_uplink_addr, uint16_t a_uplin //l_client_http_internal->socket = l_socket; l_client_http_internal->obj = a_obj; - // add to dap_worker - dap_events_socket_create_after(l_ev_socket); - - // connect struct sockaddr_in l_remote_addr; memset(&l_remote_addr, 0, sizeof(l_remote_addr)); + // get struct in_addr from ip_str + inet_pton(AF_INET, a_uplink_addr, &(l_remote_addr.sin_addr)); + //Resolve addr if + if(!l_remote_addr.sin_addr.s_addr) { + if(resolve_host(a_uplink_addr, AF_INET, &l_remote_addr.sin_addr) < 0) { + log_it(L_ERROR, "Wrong remote address '%s:%u'", a_uplink_addr, a_uplink_port); + dap_events_socket_kill_socket(l_ev_socket); + return NULL; + } + } + // connect l_remote_addr.sin_family = AF_INET; l_remote_addr.sin_port = htons(a_uplink_port); - if(inet_pton(AF_INET, a_uplink_addr, &(l_remote_addr.sin_addr)) < 0) { - log_it(L_ERROR, "Wrong remote address '%s:%u'", a_uplink_addr, a_uplink_port); - //close(l_ev_socket->socket); - dap_events_socket_kill_socket(l_ev_socket); - return NULL; + int l_err = 0; + if((l_err = connect(l_socket, (struct sockaddr *) &l_remote_addr, sizeof(struct sockaddr_in))) != -1) { + //s_set_sock_nonblock(a_client_pvt->stream_socket, false); + log_it(L_INFO, "Remote address connected (%s:%u) with sock_id %d", a_uplink_addr, a_uplink_port, l_socket); + // add to dap_worker + dap_events_socket_create_after(l_ev_socket); } else { - int l_err = 0; - if((l_err = connect(l_socket, (struct sockaddr *) &l_remote_addr, sizeof(struct sockaddr_in))) != -1) { - //s_set_sock_nonblock(a_client_pvt->stream_socket, false); - log_it(L_INFO, "Remote address connected (%s:%u) with sock_id %d", a_uplink_addr, a_uplink_port, l_socket); - } - else { - log_it(L_ERROR, "Remote address can't connected (%s:%u) with sock_id %d", a_uplink_addr, a_uplink_port, l_socket); - //l_ev_socket->no_close = false; - dap_events_socket_kill_socket(l_ev_socket); - //shutdown(l_ev_socket->socket, SHUT_RDWR); - //dap_events_socket_remove_and_delete(l_ev_socket, true); - //l_ev_socket->socket = 0; - return NULL; - } + log_it(L_ERROR, "Remote address can't connected (%s:%u) with sock_id %d err=%d", a_uplink_addr, a_uplink_port, + l_socket, errno); + //l_ev_socket->no_close = false; + dap_events_socket_kill_socket(l_ev_socket); + //shutdown(l_ev_socket->socket, SHUT_RDWR); + //dap_events_socket_remove_and_delete(l_ev_socket, true); + //l_ev_socket->socket = 0; + return NULL ; } //dap_client_pvt_t * l_client_pvt = (dap_client_pvt_t*) a_obj; @@ -372,8 +421,17 @@ void* dap_client_http_request_custom(const char *a_uplink_addr, uint16_t a_uplin // adding string for GET request char *l_get_str = NULL; if(!dap_strcmp(a_method, "GET")) { - l_get_str = dap_strdup_printf("?%s", a_request); + char l_buf[1024]; + dap_snprintf(l_buf, sizeof(l_buf), "User-Agent: Mozilla\r\n"); + if(a_cookie) { + dap_snprintf(l_buf, sizeof(l_buf), "Cookie: %s\r\n", a_cookie); + l_request_headers = dap_string_append(l_request_headers, l_buf); + } + + if(a_request) + l_get_str = dap_strdup_printf("?%s", a_request); } + // send header dap_events_socket_write_f(l_ev_socket, "%s /%s%s HTTP/1.1\r\n" "Host: %s\r\n" diff --git a/modules/net/srv/CMakeLists.txt b/modules/net/srv/CMakeLists.txt index 2e61dfc24495455bd746aa45f2a7f8a66c6b6fbb..3dddc56908a9ab7453cf77ae3d77d16c15b57940 100644 --- a/modules/net/srv/CMakeLists.txt +++ b/modules/net/srv/CMakeLists.txt @@ -1,9 +1,9 @@ cmake_minimum_required(VERSION 2.8) project (dap_chain_net_srv) -file(GLOB DAP_CHAIN_NET_SRV_SRCS *.c) +file(GLOB DAP_CHAIN_NET_SRV_SRCS *.c libmaxminddb/*.c) -file(GLOB DAP_CHAIN_NET_SRV_HEADERS include/*.h) +file(GLOB DAP_CHAIN_NET_SRV_HEADERS include/*.h libmaxminddb/*.h) add_library(${PROJECT_NAME} STATIC ${DAP_CHAIN_NET_SRV_SRCS} ${DAP_CHAIN_NET_SRV_HEADERS}) diff --git a/modules/net/srv/dap_chain_net_srv_countries.h b/modules/net/srv/dap_chain_net_srv_countries.h new file mode 100644 index 0000000000000000000000000000000000000000..06d47dd512aef5a463565213847cfab94cb0d0ae --- /dev/null +++ b/modules/net/srv/dap_chain_net_srv_countries.h @@ -0,0 +1,258 @@ +/* + * CountryCodes + * ISO, ISO3, Country, Continent + */ +const char *s_server_countries[] = { + "AD", "AND", "Andorra", "EU", + "AE", "ARE", "United Arab Emirates", "AS", + "AF", "AFG", "Afghanistan", "AS", + "AG", "ATG", "Antigua and Barbuda", "NA", + "AI", "AIA", "Anguilla", "NA", + "AL", "ALB", "Albania", "EU", + "AM", "ARM", "Armenia", "AS", + "AO", "AGO", "Angola", "AF", + "AQ", "ATA", "Antarctica", "AN", + "AR", "ARG", "Argentina", "SA", + "AS", "ASM", "American Samoa", "OC", + "AT", "AUT", "Austria", "EU", + "AU", "AUS", "Australia", "OC", + "AW", "ABW", "Aruba", "NA", + "AX", "ALA", "Aland Islands", "EU", + "AZ", "AZE", "Azerbaijan", "AS", + "BA", "BIH", "Bosnia and Herzegovina", "EU", + "BB", "BRB", "Barbados", "NA", + "BD", "BGD", "Bangladesh", "AS", + "BE", "BEL", "Belgium", "EU", + "BF", "BFA", "Burkina Faso", "AF", + "BG", "BGR", "Bulgaria", "EU", + "BH", "BHR", "Bahrain", "AS", + "BI", "BDI", "Burundi", "AF", + "BJ", "BEN", "Benin", "AF", + "BL", "BLM", "Saint Barthelemy", "NA", + "BM", "BMU", "Bermuda", "NA", + "BN", "BRN", "Brunei", "AS", + "BO", "BOL", "Bolivia", "SA", + "BQ", "BES", "Bonaire", "NA", + "BR", "BRA", "Brazil", "SA", + "BS", "BHS", "Bahamas", "NA", + "BT", "BTN", "Bhutan", "AS", + "BV", "BVT", "Bouvet Island", "AN", + "BW", "BWA", "Botswana", "AF", + "BY", "BLR", "Belarus", "EU", + "BZ", "BLZ", "Belize", "NA", + "CA", "CAN", "Canada", "NA", + "CC", "CCK", "Cocos Islands", "AS", + "CD", "COD", "Democratic Republic of the Congo", "AF", + "CF", "CAF", "Central African Republic", "AF", + "CG", "COG", "Republic of the Congo", "AF", + "CH", "CHE", "Switzerland", "EU", + "CI", "CIV", "Ivory Coast", "AF", + "CK", "COK", "Cook Islands", "OC", + "CL", "CHL", "Chile", "SA", + "CM", "CMR", "Cameroon", "AF", + "CN", "CHN", "China", "AS", + "CO", "COL", "Colombia", "SA", + "CR", "CRI", "Costa Rica", "NA", + "CU", "CUB", "Cuba", "NA", + "CV", "CPV", "Cabo Verde", "AF", + "CW", "CUW", "Curacao", "NA", + "CX", "CXR", "Christmas Island", "OC", + "CY", "CYP", "Cyprus", "EU", + "CZ", "CZE", "Czechia", "EU", + "DE", "DEU", "Germany", "EU", + "DJ", "DJI", "Djibouti", "AF", + "DK", "DNK", "Denmark", "EU", + "DM", "DMA", "Dominica", "NA", + "DO", "DOM", "Dominican Republic", "NA", + "DZ", "DZA", "Algeria", "AF", + "EC", "ECU", "Ecuador", "SA", + "EE", "EST", "Estonia", "EU", + "EG", "EGY", "Egypt", "AF", + "EH", "ESH", "Western Sahara", "AF", + "ER", "ERI", "Eritrea", "AF", + "ES", "ESP", "Spain", "EU", + "ET", "ETH", "Ethiopia", "AF", + "FI", "FIN", "Finland", "EU", + "FJ", "FJI", "Fiji", "OC", + "FK", "FLK", "Falkland Islands", "SA", + "FM", "FSM", "Micronesia", "OC", + "FO", "FRO", "Faroe Islands", "EU", + "FR", "FRA", "France", "EU", + "GA", "GAB", "Gabon", "AF", + "GB", "GBR", "United Kingdom", "EU", + "GD", "GRD", "Grenada", "NA", + "GE", "GEO", "Georgia", "AS", + "GF", "GUF", "French Guiana", "SA", + "GG", "GGY", "Guernsey", "EU", + "GH", "GHA", "Ghana", "AF", + "GI", "GIB", "Gibraltar", "EU", + "GL", "GRL", "Greenland", "NA", + "GM", "GMB", "Gambia", "AF", + "GN", "GIN", "Guinea", "AF", + "GP", "GLP", "Guadeloupe", "NA", + "GQ", "GNQ", "Equatorial Guinea", "AF", + "GR", "GRC", "Greece", "EU", + "GS", "SGS", "South Georgia and the South Sandwich Islands", "AN", + "GT", "GTM", "Guatemala", "NA", + "GU", "GUM", "Guam", "OC", + "GW", "GNB", "Guinea-Bissau", "AF", + "GY", "GUY", "Guyana", "SA", + "HK", "HKG", "Hong Kong", "AS", + "HM", "HMD", "Heard Island and McDonald Islands", "AN", + "HN", "HND", "Honduras", "NA", + "HR", "HRV", "Croatia", "EU", + "HT", "HTI", "Haiti", "NA", + "HU", "HUN", "Hungary", "EU", + "ID", "IDN", "Indonesia", "AS", + "IE", "IRL", "Ireland", "EU", + "IL", "ISR", "Israel", "AS", + "IM", "IMN", "Isle of Man", "EU", + "IN", "IND", "India", "AS", + "IO", "IOT", "British Indian Ocean Territory", "AS", + "IQ", "IRQ", "Iraq", "AS", + "IR", "IRN", "Iran", "AS", + "IS", "ISL", "Iceland", "EU", + "IT", "ITA", "Italy", "EU", + "JE", "JEY", "Jersey", "EU", + "JM", "JAM", "Jamaica", "NA", + "JO", "JOR", "Jordan", "AS", + "JP", "JPN", "Japan", "AS", + "KE", "KEN", "Kenya", "AF", + "KG", "KGZ", "Kyrgyzstan", "AS", + "KH", "KHM", "Cambodia", "AS", + "KI", "KIR", "Kiribati", "OC", + "KM", "COM", "Comoros", "AF", + "KN", "KNA", "Saint Kitts and Nevis", "NA", + "KP", "PRK", "North Korea", "AS", + "KR", "KOR", "South Korea", "AS", + "XK", "XKX", "Kosovo", "EU", + "KW", "KWT", "Kuwait", "AS", + "KY", "CYM", "Cayman Islands", "NA", + "KZ", "KAZ", "Kazakhstan", "AS", + "LA", "LAO", "Laos", "AS", + "LB", "LBN", "Lebanon", "AS", + "LC", "LCA", "Saint Lucia", "NA", + "LI", "LIE", "Liechtenstein", "EU", + "LK", "LKA", "Sri Lanka", "AS", + "LR", "LBR", "Liberia", "AF", + "LS", "LSO", "Lesotho", "AF", + "LT", "LTU", "Lithuania", "EU", + "LU", "LUX", "Luxembourg", "EU", + "LV", "LVA", "Latvia", "EU", + "LY", "LBY", "Libya", "AF", + "MA", "MAR", "Morocco", "AF", + "MC", "MCO", "Monaco", "EU", + "MD", "MDA", "Moldova", "EU", + "ME", "MNE", "Montenegro", "EU", + "MF", "MAF", "Saint Martin", "NA", + "MG", "MDG", "Madagascar", "AF", + "MH", "MHL", "Marshall Islands", "OC", + "MK", "MKD", "North Macedonia", "EU", + "ML", "MLI", "Mali", "AF", + "MM", "MMR", "Myanmar", "AS", + "MN", "MNG", "Mongolia", "AS", + "MO", "MAC", "Macao", "AS", + "MP", "MNP", "Northern Mariana Islands", "OC", + "MQ", "MTQ", "Martinique", "NA", + "MR", "MRT", "Mauritania", "AF", + "MS", "MSR", "Montserrat", "NA", + "MT", "MLT", "Malta", "EU", + "MU", "MUS", "Mauritius", "AF", + "MV", "MDV", "Maldives", "AS", + "MW", "MWI", "Malawi", "AF", + "MX", "MEX", "Mexico", "NA", + "MY", "MYS", "Malaysia", "AS", + "MZ", "MOZ", "Mozambique", "AF", + "NA", "NAM", "Namibia", "AF", + "NC", "NCL", "New Caledonia", "OC", + "NE", "NER", "Niger", "AF", + "NF", "NFK", "Norfolk Island", "OC", + "NG", "NGA", "Nigeria", "AF", + "NI", "NIC", "Nicaragua", "NA", + "NL", "NLD", "Netherlands", "EU", + "NO", "NOR", "Norway", "EU", + "NP", "NPL", "Nepal", "AS", + "NR", "NRU", "Nauru", "OC", + "NU", "NIU", "Niue", "OC", + "NZ", "NZL", "New Zealand", "OC", + "OM", "OMN", "Oman", "AS", + "PA", "PAN", "Panama", "NA", + "PE", "PER", "Peru", "SA", + "PF", "PYF", "French Polynesia", "OC", + "PG", "PNG", "Papua New Guinea", "OC", + "PH", "PHL", "Philippines", "AS", + "PK", "PAK", "Pakistan", "AS", + "PL", "POL", "Poland", "EU", + "PM", "SPM", "Saint Pierre and Miquelon", "NA", + "PN", "PCN", "Pitcairn", "OC", + "PR", "PRI", "Puerto Rico", "NA", + "PS", "PSE", "Palestinian Territory", "AS", + "PT", "PRT", "Portugal", "EU", + "PW", "PLW", "Palau", "OC", + "PY", "PRY", "Paraguay", "SA", + "QA", "QAT", "Qatar", "AS", + "RE", "REU", "Reunion", "AF", + "RO", "ROU", "Romania", "EU", + "RS", "SRB", "Serbia", "EU", + "RU", "RUS", "Russia", "EU", + "RW", "RWA", "Rwanda", "AF", + "SA", "SAU", "Saudi Arabia", "AS", + "SB", "SLB", "Solomon Islands", "OC", + "SC", "SYC", "Seychelles", "AF", + "SD", "SDN", "Sudan", "AF", + "SS", "SSD", "South Sudan", "AF", + "SE", "SWE", "Sweden", "EU", + "SG", "SGP", "Singapore", "AS", + "SH", "SHN", "Saint Helena", "AF", + "SI", "SVN", "Slovenia", "EU", + "SJ", "SJM", "Svalbard and Jan Mayen", "EU", + "SK", "SVK", "Slovakia", "EU", + "SL", "SLE", "Sierra Leone", "AF", + "SM", "SMR", "San Marino", "EU", + "SN", "SEN", "Senegal", "AF", + "SO", "SOM", "Somalia", "AF", + "SR", "SUR", "Suriname", "SA", + "ST", "STP", "Sao Tome and Principe", "AF", + "SV", "SLV", "El Salvador", "NA", + "SX", "SXM", "Sint Maarten", "NA", + "SY", "SYR", "Syria", "AS", + "SZ", "SWZ", "Eswatini", "AF", + "TC", "TCA", "Turks and Caicos Islands", "NA", + "TD", "TCD", "Chad", "AF", + "TF", "ATF", "French Southern Territories", "AN", + "TG", "TGO", "Togo", "AF", + "TH", "THA", "Thailand", "AS", + "TJ", "TJK", "Tajikistan", "AS", + "TK", "TKL", "Tokelau", "OC", + "TL", "TLS", "Timor Leste", "OC", + "TM", "TKM", "Turkmenistan", "AS", + "TN", "TUN", "Tunisia", "AF", + "TO", "TON", "Tonga", "OC", + "TR", "TUR", "Turkey", "AS", + "TT", "TTO", "Trinidad and Tobago", "NA", + "TV", "TUV", "Tuvalu", "OC", + "TW", "TWN", "Taiwan", "AS", + "TZ", "TZA", "Tanzania", "AF", + "UA", "UKR", "Ukraine", "EU", + "UG", "UGA", "Uganda", "AF", + "UM", "UMI", "United States Minor Outlying Islands", "OC", + "US", "USA", "United States", "NA", + "UY", "URY", "Uruguay", "SA", + "UZ", "UZB", "Uzbekistan", "AS", + "VA", "VAT", "Vatican", "EU", + "VC", "VCT", "Saint Vincent and the Grenadines", "NA", + "VE", "VEN", "Venezuela", "SA", + "VG", "VGB", "British Virgin Islands", "NA", + "VI", "VIR", "U.S. Virgin Islands", "NA", + "VN", "VNM", "Vietnam", "AS", + "VU", "VUT", "Vanuatu", "OC", + "WF", "WLF", "Wallis and Futuna", "OC", + "WS", "WSM", "Samoa", "OC", + "YE", "YEM", "Yemen", "AS", + "YT", "MYT", "Mayotte", "AF", + "ZA", "ZAF", "South Africa", "AF", + "ZM", "ZMB", "Zambia", "AF", + "ZW", "ZWE", "Zimbabwe", "AF", + "CS", "SCG", "Serbia and Montenegro", "EU", + "AN", "ANT", "Netherlands Antilles", "NA" +}; diff --git a/modules/net/srv/dap_chain_net_srv_geoip.c b/modules/net/srv/dap_chain_net_srv_geoip.c new file mode 100644 index 0000000000000000000000000000000000000000..a0f1a31b0b300f7c9d755fda8a7057b377f1c7f2 --- /dev/null +++ b/modules/net/srv/dap_chain_net_srv_geoip.c @@ -0,0 +1,254 @@ +/* + * Authors: + * Aleksandr Lysikov <alexander.lysikov@demlabs.net> + * DeM Labs Inc. https://demlabs.net + * DeM Labs Open source community https://github.com/demlabsinc + * Copyright (c) 2020 + * All rights reserved. + + This file is part of DAP (Deus Applications Prototypes) the open source project + + DAP (Deus Applicaions Prototypes) is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + DAP is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with any DAP based project. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <stdio.h> +#include <stddef.h> + +#include "dap_common.h" +#include "dap_strfuncs.h" +#include "dap_file_utils.h" +#include "dap_enc_key.h" +#include "dap_enc_base64.h" +#include "dap_client_http.h" +#include "dap_chain_net_srv_geoip.h" +#include "libmaxminddb/maxminddb.h" + +#define LOG_TAG "chain_net_srv_geoip" +#define LOCALE_DEFAULT "en" + +/** + * @brief m_request_response + * @param a_response + * @param a_response_size + * @param a_obj + */ +static void m_request_getip_response(void * a_response, size_t a_response_size, void * a_obj) +{ + char *l_addr = (char *) a_obj; + //printf("m_request_getip_response %s\n", a_response); +} + +static void m_request_getip_request_error(int a_err_code, void *a_obj) +{ + char *l_addr = (char *) a_obj; + //printf("m_request_getip_request_error %s\n", l_addr); +} + +geoip_info_t *chain_net_geoip_get_ip_info_by_web(const char *a_ip_str) +{ + // https://geoip.maxmind.com/geoip/v2.1/insights/<ip> + // https://geoip.maxmind.com/geoip/v2.1/city/<ip> + char *l_path = dap_strdup_printf("/geoip/v2.1/insights/%s", a_ip_str); + //104.16.38.47:443 + // geoip.maxmind.com + char l_out[40]; + //Account/User ID 288651 + //License key + // https://dev.maxmind.com/geoip/geoip2/web-services/ + const char *user_id = "288651"; + const char *license_key = "1JGvRmd3Ux1kcBkb"; + char *l_auth = dap_strdup_printf("%s:%s", user_id, license_key); + size_t l_out_len = dap_enc_base64_encode(l_auth, strlen(l_auth), l_out, DAP_ENC_DATA_TYPE_B64); + char * l_custom = l_out_len > 0 ? dap_strdup_printf("Authorization: Basic %s", l_out) : NULL; + size_t l_custom_count = 1; + // todo just need to finish up https request + dap_client_http_request_custom("geoip.maxmind.com", 443, "GET", "application/json", l_path, NULL, + 0, NULL, m_request_getip_response, m_request_getip_request_error, NULL, &l_custom, l_custom_count); + return NULL; +} + +/* + * Get value from mmdb by 2 strings + */ +static int mmdb_get_value_double2(MMDB_lookup_result_s *a_result, const char *a_one, const char *a_two, double *a_out_double) +{ + if (!a_out_double || !a_result || !a_result->found_entry) + return -1; + MMDB_entry_data_s entry_data; + int l_status = MMDB_get_value(&a_result->entry, &entry_data, a_one, a_two, NULL); + if (MMDB_SUCCESS != l_status) { + log_it(L_DEBUG, "False get_value [%s->%s] with errcode=%d", a_one, a_two, l_status); + return -2; + } + if (entry_data.has_data) { + if (a_out_double && entry_data.type == MMDB_DATA_TYPE_DOUBLE) { + //memcpy(a_out_double, &entry_data.double_value, entry_data.data_size); + *a_out_double = entry_data.double_value; + } else + log_it(L_DEBUG, + "error value [%s->%s] has size=%d(>0) type=%d(%d)", + a_one, a_two, entry_data.data_size, + entry_data.type, MMDB_DATA_TYPE_DOUBLE); + } + else + return -3; + return 0; +} + +/* + * Get value from mmdb by 2 strings + */ +static int mmdb_get_value_str2(MMDB_lookup_result_s *a_result, const char *a_one, const char *a_two, char *a_out_str, size_t a_out_str_size) +{ + if (!a_out_str || !a_result || !a_result->found_entry) + return -1; + MMDB_entry_data_s entry_data; + int l_status = MMDB_get_value(&a_result->entry, &entry_data, a_one, a_two, NULL); + if (MMDB_SUCCESS != l_status) { + log_it(L_DEBUG, "False get_value [%s->%s] with errcode=%d", a_one, a_two, l_status); + return -2; + } + if (entry_data.has_data) { + if (entry_data.data_size > 0 && entry_data.type == MMDB_DATA_TYPE_UTF8_STRING) { + size_t l_size = min(a_out_str_size-1, entry_data.data_size); + strncpy(a_out_str, entry_data.utf8_string, l_size); + a_out_str[l_size] = 0; + } else + log_it(L_DEBUG, + "error value [%s->%s] has size=%d(>0) type=%d(%d)", + a_one, a_two, entry_data.data_size, + entry_data.type, MMDB_DATA_TYPE_UTF8_STRING); + } + else + return -3; + return 0; +} + +/* + * Get value from mmdb by 3 strings + */ +static int mmdb_get_value_str3(MMDB_lookup_result_s *a_result, const char *a_one, const char *a_two, const char *a_three, char *a_out_str, size_t a_out_str_size) +{ + if (!a_out_str || !a_result || !a_result->found_entry) + return -1; + MMDB_entry_data_s entry_data; + int l_status = MMDB_get_value(&a_result->entry, &entry_data, a_one, a_two, a_three, NULL); + if (MMDB_SUCCESS != l_status) { + log_it(L_DEBUG, "False get_value [%s->%s->%s] with errcode=%d", a_one, a_two, a_three, l_status); + return -2; + } + if (entry_data.has_data) { + if (entry_data.data_size > 0 && entry_data.type == MMDB_DATA_TYPE_UTF8_STRING) { + size_t l_size = min(a_out_str_size-1, entry_data.data_size); + strncpy(a_out_str, entry_data.utf8_string, l_size); + a_out_str[l_size] = 0; + } else + log_it(L_DEBUG, + "error value [%s->%s->%s] has size=%d(>0) type=%d(%d)", + a_one, a_two, a_three, entry_data.data_size, + entry_data.type, MMDB_DATA_TYPE_UTF8_STRING); + } + else + return -3; + return 0; +} + +geoip_info_t *chain_net_geoip_get_ip_info_by_local_db(const char *a_ip_str, const char *a_locale) +{ + // https://geoip.maxmind.com/geoip/v2.1/city/178.7.88.55 + // https://maxmind.github.io/libmaxminddb/ + char *l_file_db_name = dap_strdup_printf("%s/share/geoip/GeoLite2-City.mmdb", g_sys_dir_path); + if(!dap_file_test(l_file_db_name)) { + DAP_DELETE(l_file_db_name); + return NULL ; + } + MMDB_s mmdb; + int l_status = MMDB_open(l_file_db_name, MMDB_MODE_MMAP, &mmdb); + if(MMDB_SUCCESS != l_status) { + log_it(L_WARNING, "geoip file %s opened with errcode=%d", l_file_db_name, l_status); + return NULL ; + } + DAP_DELETE(l_file_db_name); + + geoip_info_t *l_ret = DAP_NEW_Z(geoip_info_t); + + int gai_error, mmdb_error; + MMDB_lookup_result_s result = MMDB_lookup_string(&mmdb, a_ip_str, &gai_error, &mmdb_error); + if (0 != gai_error || MMDB_SUCCESS != mmdb_error) { + log_it(L_WARNING, "no lookup ip=%s with errcode=%d", a_ip_str, l_status); + } + + // continent + if (mmdb_get_value_str3(&result, "continent", "names", a_locale, l_ret->continent, sizeof(l_ret->continent))) { + if (mmdb_get_value_str3(&result, "continent", "names", LOCALE_DEFAULT, l_ret->continent, sizeof(l_ret->continent))) { + MMDB_close(&mmdb); + DAP_FREE(l_ret); + return NULL; + } + } + // country + if (mmdb_get_value_str3(&result, "country", "names", a_locale, l_ret->country_name, sizeof(l_ret->country_name))) { + if (mmdb_get_value_str3(&result, "country", "names", LOCALE_DEFAULT, l_ret->country_name, sizeof(l_ret->country_name))) { + MMDB_close(&mmdb); + DAP_FREE(l_ret); + return NULL; + } + } + // all the country names http://download.geonames.org/export/dump/countryInfo.txt + if (mmdb_get_value_str2(&result, "country", "iso_code", l_ret->country_code, sizeof(l_ret->country_code))) { + MMDB_close(&mmdb); + DAP_FREE(l_ret); + return NULL; + } + // city + /*if (mmdb_get_value_str3(&result, "city", "names", a_locale, l_ret->city_name, sizeof(l_ret->city_name))) { + if (mmdb_get_value_str3(&result, "city", "names", LOCALE_DEFAULT, l_ret->city_name, sizeof(l_ret->city_name))) { + MMDB_close(&mmdb); + DAP_FREE(l_ret); + return NULL; + } + }*/ + + //location + if (mmdb_get_value_double2(&result, "location", "latitude", &l_ret->latitude)) { + MMDB_close(&mmdb); + DAP_FREE(l_ret); + return NULL; + } + if (mmdb_get_value_double2(&result, "location", "longitude", &l_ret->longitude)) { + MMDB_close(&mmdb); + DAP_FREE(l_ret); + return NULL; + } + + // IP + /*if (mmdb_get_value_str2(&result, "traits", "ip_address", l_ret->ip_str, sizeof(l_ret->ip_str))) { + MMDB_close(&mmdb); + DAP_FREE(l_ret); + return NULL; + }*/ + int a = sizeof(l_ret->ip_str); + size_t l_size = min(dap_strlen(a_ip_str), sizeof(l_ret->ip_str)); + l_ret->ip_str[l_size] = 0; + strncpy(l_ret->ip_str, a_ip_str, l_size); + + MMDB_close(&mmdb); + return l_ret; +} + +geoip_info_t *chain_net_geoip_get_ip_info(const char *a_ip_str) +{ + return chain_net_geoip_get_ip_info_by_local_db(a_ip_str, "en"); + //return chain_net_geoip_get_ip_info_by_web(a_ip_str); +} diff --git a/modules/net/srv/dap_chain_net_srv_geoip.h b/modules/net/srv/dap_chain_net_srv_geoip.h new file mode 100644 index 0000000000000000000000000000000000000000..714dbc62f243ff722285a3633aaaf04324787352 --- /dev/null +++ b/modules/net/srv/dap_chain_net_srv_geoip.h @@ -0,0 +1,37 @@ +/* + * Authors: + * Aleksandr Lysikov <alexander.lysikov@demlabs.net> + * DeM Labs Inc. https://demlabs.net + * DeM Labs Open source community https://github.com/demlabsinc + * Copyright (c) 2020 + * All rights reserved. + + This file is part of DAP (Deus Applications Prototypes) the open source project + + DAP (Deus Applicaions Prototypes) is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + DAP is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with any DAP based project. If not, see <http://www.gnu.org/licenses/>. + */ + +typedef struct geoip_info { + + char ip_str[20]; + char continent[60]; + char country_name[64]; + char country_code[3];// iso_code, all the country names http://download.geonames.org/export/dump/countryInfo.txt + char city_name[64]; + double latitude; + double longitude; + +} geoip_info_t; + +geoip_info_t *chain_net_geoip_get_ip_info(const char *a_ip_str); diff --git a/modules/net/srv/dap_chain_net_srv_order.c b/modules/net/srv/dap_chain_net_srv_order.c index 104424e56a1842fd67c42f38aa0cd2ed3c938951..81c490d689347d6ec19f76c970a27a76edd3f3b6 100644 --- a/modules/net/srv/dap_chain_net_srv_order.c +++ b/modules/net/srv/dap_chain_net_srv_order.c @@ -22,13 +22,28 @@ along with any DAP based project. If not, see <http://www.gnu.org/licenses/>. */ +#include <stdio.h> +#include <strings.h> + #include "dap_chain_net_srv_order.h" #include "dap_hash.h" #include "dap_chain_global_db.h" +#include "dap_chain_net_srv_countries.h" +//#include "dap_chain_net_srv_geoip.h" #define LOG_TAG "dap_chain_net_srv_order" +/* +Continent codes : +AF : Africa geonameId=6255146 +AS : Asia geonameId=6255147 +EU : Europe geonameId=6255148 +NA : North America geonameId=6255149 +OC : Oceania geonameId=6255151 +SA : South America geonameId=6255150 +AN : Antarctica geonameId=6255152 + */ char *s_server_continents[]={ "None", "Africa", @@ -36,7 +51,10 @@ char *s_server_continents[]={ "North America", "South America", "Southeast Asia", - "Near East", + "Asia", + //"Near East", + "Oceania", + "Antarctica" }; /** @@ -46,6 +64,7 @@ char *s_server_continents[]={ int dap_chain_net_srv_order_init(void) { + //geoip_info_t *l_ipinfo = chain_net_geoip_get_ip_info("8.8.8.8"); return 0; } @@ -112,8 +131,7 @@ bool dap_chain_net_srv_order_get_continent_region(dap_chain_net_srv_order_t *a_o memcpy(a_continent_num, a_order->ext + 1, sizeof(uint8_t)); else a_continent_num = 0; - }else - a_continent_num = 0; + } if(a_region) { size_t l_size = a_order->ext_size - sizeof(uint8_t) - 1; if(l_size > 0) { @@ -126,6 +144,26 @@ bool dap_chain_net_srv_order_get_continent_region(dap_chain_net_srv_order_t *a_o return true; } +/** + * @brief dap_chain_net_srv_order_get_country_code + * @param a_order + */ +const char* dap_chain_net_srv_order_get_country_code(dap_chain_net_srv_order_t *a_order) +{ + char *l_region = NULL; + if (!dap_chain_net_srv_order_get_continent_region(a_order, NULL, &l_region)) + return NULL; + int l_countries = sizeof(s_server_countries)/sizeof(char*); + for (int i = 0; i < l_countries; i+=4) { + if(l_region && (!strcasecmp(l_region, s_server_countries[i+1]) || !strcasecmp(l_region, s_server_countries[i+2]))){ + const char *l_country_code = s_server_countries[i]; + DAP_DELETE(l_region); + return l_country_code; + } + } + DAP_DELETE(l_region); + return NULL; +} /** * @brief dap_chain_net_srv_order_continents_count diff --git a/modules/net/srv/include/dap_chain_net_srv_order.h b/modules/net/srv/include/dap_chain_net_srv_order.h index 3aa88fd18145045a68c158a1edd97bd760588f22..d99377fcbf8935a2601800a3915bee50b0d8a8c5 100644 --- a/modules/net/srv/include/dap_chain_net_srv_order.h +++ b/modules/net/srv/include/dap_chain_net_srv_order.h @@ -57,6 +57,7 @@ size_t dap_chain_net_srv_order_get_size(dap_chain_net_srv_order_t *a_order); bool dap_chain_net_srv_order_set_continent_region(dap_chain_net_srv_order_t **a_order, uint8_t a_continent_num, const char *a_region); bool dap_chain_net_srv_order_get_continent_region(dap_chain_net_srv_order_t *a_order, uint8_t *a_continent_num, char **a_region); +const char* dap_chain_net_srv_order_get_country_code(dap_chain_net_srv_order_t *a_order); size_t dap_chain_net_srv_order_continents_count(void); const char* dap_chain_net_srv_order_continent_to_str(int8_t a_num); int8_t dap_chain_net_srv_order_continent_to_num(const char *l_continent_str); diff --git a/modules/net/srv/libmaxminddb/data-pool.c b/modules/net/srv/libmaxminddb/data-pool.c new file mode 100644 index 0000000000000000000000000000000000000000..48521b64dec3df796ca876011ee4d6c65d2a4efb --- /dev/null +++ b/modules/net/srv/libmaxminddb/data-pool.c @@ -0,0 +1,180 @@ +#include "data-pool.h" +#include "maxminddb.h" + +#include <stdbool.h> +#include <stddef.h> +#include <stdlib.h> + +static bool can_multiply(size_t const, size_t const, size_t const); + +// Allocate an MMDB_data_pool_s. It initially has space for size +// MMDB_entry_data_list_s structs. +MMDB_data_pool_s *data_pool_new(size_t const size) +{ + MMDB_data_pool_s *const pool = calloc(1, sizeof(MMDB_data_pool_s)); + if (!pool) { + return NULL; + } + + if (size == 0 || + !can_multiply(SIZE_MAX, size, sizeof(MMDB_entry_data_list_s))) { + data_pool_destroy(pool); + return NULL; + } + pool->size = size; + pool->blocks[0] = calloc(pool->size, sizeof(MMDB_entry_data_list_s)); + if (!pool->blocks[0]) { + data_pool_destroy(pool); + return NULL; + } + pool->blocks[0]->pool = pool; + + pool->sizes[0] = size; + + pool->block = pool->blocks[0]; + + return pool; +} + +// Determine if we can multiply m*n. We can do this if the result will be below +// the given max. max will typically be SIZE_MAX. +// +// We want to know if we'll wrap around. +static bool can_multiply(size_t const max, size_t const m, size_t const n) +{ + if (m == 0) { + return false; + } + + return n <= max / m; +} + +// Clean up the data pool. +void data_pool_destroy(MMDB_data_pool_s *const pool) +{ + if (!pool) { + return; + } + + for (size_t i = 0; i <= pool->index; i++) { + free(pool->blocks[i]); + } + + free(pool); +} + +// Claim a new struct from the pool. Doing this may cause the pool's size to +// grow. +MMDB_entry_data_list_s *data_pool_alloc(MMDB_data_pool_s *const pool) +{ + if (!pool) { + return NULL; + } + + if (pool->used < pool->size) { + MMDB_entry_data_list_s *const element = pool->block + pool->used; + pool->used++; + return element; + } + + // Take it from a new block of memory. + + size_t const new_index = pool->index + 1; + if (new_index == DATA_POOL_NUM_BLOCKS) { + // See the comment about not growing this on DATA_POOL_NUM_BLOCKS. + return NULL; + } + + if (!can_multiply(SIZE_MAX, pool->size, 2)) { + return NULL; + } + size_t const new_size = pool->size * 2; + + if (!can_multiply(SIZE_MAX, new_size, sizeof(MMDB_entry_data_list_s))) { + return NULL; + } + pool->blocks[new_index] = calloc(new_size, sizeof(MMDB_entry_data_list_s)); + if (!pool->blocks[new_index]) { + return NULL; + } + + // We don't need to set this, but it's useful for introspection in tests. + pool->blocks[new_index]->pool = pool; + + pool->index = new_index; + pool->block = pool->blocks[pool->index]; + + pool->size = new_size; + pool->sizes[pool->index] = pool->size; + + MMDB_entry_data_list_s *const element = pool->block; + pool->used = 1; + return element; +} + +// Turn the structs in the array-like pool into a linked list. +// +// Before calling this function, the list isn't linked up. +MMDB_entry_data_list_s *data_pool_to_list(MMDB_data_pool_s *const pool) +{ + if (!pool) { + return NULL; + } + + if (pool->index == 0 && pool->used == 0) { + return NULL; + } + + for (size_t i = 0; i <= pool->index; i++) { + MMDB_entry_data_list_s *const block = pool->blocks[i]; + + size_t size = pool->sizes[i]; + if (i == pool->index) { + size = pool->used; + } + + for (size_t j = 0; j < size - 1; j++) { + MMDB_entry_data_list_s *const cur = block + j; + cur->next = block + j + 1; + } + + if (i < pool->index) { + MMDB_entry_data_list_s *const last = block + size - 1; + last->next = pool->blocks[i + 1]; + } + } + + return pool->blocks[0]; +} + +#ifdef TEST_DATA_POOL + +#include <libtap/tap.h> +#include <maxminddb_test_helper.h> + +static void test_can_multiply(void); + +int main(void) +{ + plan(NO_PLAN); + test_can_multiply(); + done_testing(); +} + +static void test_can_multiply(void) +{ + { + ok(can_multiply(SIZE_MAX, 1, SIZE_MAX), "1*SIZE_MAX is ok"); + } + + { + ok(!can_multiply(SIZE_MAX, 2, SIZE_MAX), "2*SIZE_MAX is not ok"); + } + + { + ok(can_multiply(SIZE_MAX, 10240, sizeof(MMDB_entry_data_list_s)), + "1024 entry_data_list_s's are okay"); + } +} + +#endif diff --git a/modules/net/srv/libmaxminddb/data-pool.h b/modules/net/srv/libmaxminddb/data-pool.h new file mode 100644 index 0000000000000000000000000000000000000000..25d09923e0cc2c301576037e4ba65548ce42b4fb --- /dev/null +++ b/modules/net/srv/libmaxminddb/data-pool.h @@ -0,0 +1,52 @@ +#ifndef DATA_POOL_H +#define DATA_POOL_H + +#include "maxminddb.h" + +#include <stdbool.h> +#include <stddef.h> + +// This should be large enough that we never need to grow the array of pointers +// to blocks. 32 is enough. Even starting out of with size 1 (1 struct), the +// 32nd element alone will provide 2**32 structs as we exponentially increase +// the number in each block. Being confident that we do not have to grow the +// array lets us avoid writing code to do that. That code would be risky as it +// would rarely be hit and likely not be well tested. +#define DATA_POOL_NUM_BLOCKS 32 + +// A pool of memory for MMDB_entry_data_list_s structs. This is so we can +// allocate multiple up front rather than one at a time for performance +// reasons. +// +// The order you add elements to it (by calling data_pool_alloc()) ends up as +// the order of the list. +// +// The memory only grows. There is no support for releasing an element you take +// back to the pool. +typedef struct MMDB_data_pool_s { + // Index of the current block we're allocating out of. + size_t index; + + // The size of the current block, counting by structs. + size_t size; + + // How many used in the current block, counting by structs. + size_t used; + + // The current block we're allocating out of. + MMDB_entry_data_list_s *block; + + // The size of each block. + size_t sizes[DATA_POOL_NUM_BLOCKS]; + + // An array of pointers to blocks of memory holding space for list + // elements. + MMDB_entry_data_list_s *blocks[DATA_POOL_NUM_BLOCKS]; +} MMDB_data_pool_s; + +MMDB_data_pool_s *data_pool_new(size_t const); +void data_pool_destroy(MMDB_data_pool_s *const); +MMDB_entry_data_list_s *data_pool_alloc(MMDB_data_pool_s *const); +MMDB_entry_data_list_s *data_pool_to_list(MMDB_data_pool_s *const); + +#endif diff --git a/modules/net/srv/libmaxminddb/maxminddb-compat-util.h b/modules/net/srv/libmaxminddb/maxminddb-compat-util.h new file mode 100644 index 0000000000000000000000000000000000000000..e3f0320f29b9180305ec3b8484fc6a00432011d9 --- /dev/null +++ b/modules/net/srv/libmaxminddb/maxminddb-compat-util.h @@ -0,0 +1,167 @@ +#include <stdlib.h> +#include <string.h> + +/* *INDENT-OFF* */ + +/* The memmem, strdup, and strndup functions were all copied from the + * FreeBSD source, along with the relevant copyright notice. + * + * It'd be nicer to simply use the functions available on the system if they + * exist, but there doesn't seem to be a good way to detect them without also + * defining things like _GNU_SOURCE, which we want to avoid, because then we + * end up _accidentally_ using GNU features without noticing, which then + * breaks on systems like OSX. + * + * C is fun! */ + +/* Applies to memmem implementation */ +/*- + * Copyright (c) 2005 Pascal Gloor <pascal.gloor@spale.com> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +static void * +mmdb_memmem(const void *l, size_t l_len, const void *s, size_t s_len) +{ + register char *cur, *last; + const char *cl = (const char *)l; + const char *cs = (const char *)s; + + /* we need something to compare */ + if (l_len == 0 || s_len == 0) + return NULL; + + /* "s" must be smaller or equal to "l" */ + if (l_len < s_len) + return NULL; + + /* special case where s_len == 1 */ + if (s_len == 1) + return memchr(l, (int)*cs, l_len); + + /* the last position where its possible to find "s" in "l" */ + last = (char *)cl + l_len - s_len; + + for (cur = (char *)cl; cur <= last; cur++) + if (cur[0] == cs[0] && memcmp(cur, cs, s_len) == 0) + return cur; + + return NULL; +} + +/* Applies to strnlen implementation */ +/*- + * Copyright (c) 2009 David Schultz <das@FreeBSD.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +static size_t +mmdb_strnlen(const char *s, size_t maxlen) +{ + size_t len; + + for (len = 0; len < maxlen; len++, s++) { + if (!*s) + break; + } + return (len); +} + +/* Applies to strdup and strndup implementation */ +/* + * Copyright (c) 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +static char * +mmdb_strdup(const char *str) +{ + size_t len; + char *copy; + + len = strlen(str) + 1; + if ((copy = malloc(len)) == NULL) + return (NULL); + memcpy(copy, str, len); + return (copy); +} + +static char * +mmdb_strndup(const char *str, size_t n) +{ + size_t len; + char *copy; + + len = mmdb_strnlen(str, n); + if ((copy = malloc(len + 1)) == NULL) + return (NULL); + memcpy(copy, str, len); + copy[len] = '\0'; + return (copy); +} +/* *INDENT-ON* */ diff --git a/modules/net/srv/libmaxminddb/maxminddb.c b/modules/net/srv/libmaxminddb/maxminddb.c new file mode 100644 index 0000000000000000000000000000000000000000..e7c9d3b921d2b3a431b0017c92fb5a2f26aed396 --- /dev/null +++ b/modules/net/srv/libmaxminddb/maxminddb.c @@ -0,0 +1,2154 @@ +#if HAVE_CONFIG_H +#include <config.h> +#endif +#include "data-pool.h" +#include "maxminddb.h" +#include "maxminddb-compat-util.h" +#include <assert.h> +#include <errno.h> +#include <fcntl.h> +#include <inttypes.h> +#include <stdint.h> +#include <stdlib.h> +#include <string.h> +#include <sys/stat.h> + +#ifdef _WIN32 +#ifndef UNICODE +#define UNICODE +#endif +#include <windows.h> +#include <ws2ipdef.h> +#else +#include <arpa/inet.h> +#include <sys/mman.h> +#include <unistd.h> +#endif + +#define MMDB_DATA_SECTION_SEPARATOR (16) +#define MAXIMUM_DATA_STRUCTURE_DEPTH (512) + +#ifdef MMDB_DEBUG +#define LOCAL +#define DEBUG_MSG(msg) fprintf(stderr, msg "\n") +#define DEBUG_MSGF(fmt, ...) fprintf(stderr, fmt "\n", __VA_ARGS__) +#define DEBUG_BINARY(fmt, byte) \ + do { \ + char *binary = byte_to_binary(byte); \ + if (NULL == binary) { \ + fprintf(stderr, "Malloc failed in DEBUG_BINARY\n"); \ + abort(); \ + } \ + fprintf(stderr, fmt "\n", binary); \ + free(binary); \ + } while (0) +#define DEBUG_NL fprintf(stderr, "\n") +#else +#define LOCAL static +#define DEBUG_MSG(...) +#define DEBUG_MSGF(...) +#define DEBUG_BINARY(...) +#define DEBUG_NL +#endif + +#ifdef MMDB_DEBUG +char *byte_to_binary(uint8_t byte) +{ + char *bits = malloc(sizeof(char) * 9); + if (NULL == bits) { + return bits; + } + + for (uint8_t i = 0; i < 8; i++) { + bits[i] = byte & (128 >> i) ? '1' : '0'; + } + bits[8] = '\0'; + + return bits; +} + +char *type_num_to_name(uint8_t num) +{ + switch (num) { + case 0: + return "extended"; + case 1: + return "pointer"; + case 2: + return "utf8_string"; + case 3: + return "double"; + case 4: + return "bytes"; + case 5: + return "uint16"; + case 6: + return "uint32"; + case 7: + return "map"; + case 8: + return "int32"; + case 9: + return "uint64"; + case 10: + return "uint128"; + case 11: + return "array"; + case 12: + return "container"; + case 13: + return "end_marker"; + case 14: + return "boolean"; + case 15: + return "float"; + default: + return "unknown type"; + } +} +#endif + +/* None of the values we check on the lhs are bigger than uint32_t, so on + * platforms where SIZE_MAX is a 64-bit integer, this would be a no-op, and it + * makes the compiler complain if we do the check anyway. */ +#if SIZE_MAX == UINT32_MAX +#define MAYBE_CHECK_SIZE_OVERFLOW(lhs, rhs, error) \ + if ((lhs) > (rhs)) { \ + return error; \ + } +#else +#define MAYBE_CHECK_SIZE_OVERFLOW(...) +#endif + +typedef struct record_info_s { + uint16_t record_length; + uint32_t (*left_record_getter)(const uint8_t *); + uint32_t (*right_record_getter)(const uint8_t *); + uint8_t right_record_offset; +} record_info_s; + +#define METADATA_MARKER "\xab\xcd\xefMaxMind.com" +/* This is 128kb */ +#define METADATA_BLOCK_MAX_SIZE 131072 + +// 64 leads us to allocating 4 KiB on a 64bit system. +#define MMDB_POOL_INIT_SIZE 64 + +LOCAL int map_file(MMDB_s *const mmdb); +LOCAL const uint8_t *find_metadata(const uint8_t *file_content, + ssize_t file_size, uint32_t *metadata_size); +LOCAL int read_metadata(MMDB_s *mmdb); +LOCAL MMDB_s make_fake_metadata_db(const MMDB_s *const mmdb); +LOCAL int value_for_key_as_uint16(MMDB_entry_s *start, char *key, + uint16_t *value); +LOCAL int value_for_key_as_uint32(MMDB_entry_s *start, char *key, + uint32_t *value); +LOCAL int value_for_key_as_uint64(MMDB_entry_s *start, char *key, + uint64_t *value); +LOCAL int value_for_key_as_string(MMDB_entry_s *start, char *key, + char const **value); +LOCAL int populate_languages_metadata(MMDB_s *mmdb, MMDB_s *metadata_db, + MMDB_entry_s *metadata_start); +LOCAL int populate_description_metadata(MMDB_s *mmdb, MMDB_s *metadata_db, + MMDB_entry_s *metadata_start); +LOCAL int resolve_any_address(const char *ipstr, struct addrinfo **addresses); +LOCAL int find_address_in_search_tree(const MMDB_s *const mmdb, + uint8_t *address, + sa_family_t address_family, + MMDB_lookup_result_s *result); +LOCAL record_info_s record_info_for_database(const MMDB_s *const mmdb); +LOCAL int find_ipv4_start_node(MMDB_s *const mmdb); +LOCAL uint8_t record_type(const MMDB_s *const mmdb, uint64_t record); +LOCAL uint32_t get_left_28_bit_record(const uint8_t *record); +LOCAL uint32_t get_right_28_bit_record(const uint8_t *record); +LOCAL uint32_t data_section_offset_for_record(const MMDB_s *const mmdb, + uint64_t record); +LOCAL int path_length(va_list va_path); +LOCAL int lookup_path_in_array(const char *path_elem, const MMDB_s *const mmdb, + MMDB_entry_data_s *entry_data); +LOCAL int lookup_path_in_map(const char *path_elem, const MMDB_s *const mmdb, + MMDB_entry_data_s *entry_data); +LOCAL int skip_map_or_array(const MMDB_s *const mmdb, + MMDB_entry_data_s *entry_data); +LOCAL int decode_one_follow(const MMDB_s *const mmdb, uint32_t offset, + MMDB_entry_data_s *entry_data); +LOCAL int decode_one(const MMDB_s *const mmdb, uint32_t offset, + MMDB_entry_data_s *entry_data); +LOCAL int get_ext_type(int raw_ext_type); +LOCAL uint32_t get_ptr_from(uint8_t ctrl, uint8_t const *const ptr, + int ptr_size); +LOCAL int get_entry_data_list(const MMDB_s *const mmdb, + uint32_t offset, + MMDB_entry_data_list_s *const entry_data_list, + MMDB_data_pool_s *const pool, + int depth); +LOCAL float get_ieee754_float(const uint8_t *restrict p); +LOCAL double get_ieee754_double(const uint8_t *restrict p); +LOCAL uint32_t get_uint32(const uint8_t *p); +LOCAL uint32_t get_uint24(const uint8_t *p); +LOCAL uint32_t get_uint16(const uint8_t *p); +LOCAL uint64_t get_uintX(const uint8_t *p, int length); +LOCAL int32_t get_sintX(const uint8_t *p, int length); +LOCAL void free_mmdb_struct(MMDB_s *const mmdb); +LOCAL void free_languages_metadata(MMDB_s *mmdb); +LOCAL void free_descriptions_metadata(MMDB_s *mmdb); +LOCAL MMDB_entry_data_list_s *dump_entry_data_list( + FILE *stream, MMDB_entry_data_list_s *entry_data_list, int indent, + int *status); +LOCAL void print_indentation(FILE *stream, int i); +LOCAL char *bytes_to_hex(uint8_t *bytes, uint32_t size); + +#define CHECKED_DECODE_ONE(mmdb, offset, entry_data) \ + do { \ + int status = decode_one(mmdb, offset, entry_data); \ + if (MMDB_SUCCESS != status) { \ + DEBUG_MSGF("CHECKED_DECODE_ONE failed." \ + " status = %d (%s)", status, MMDB_strerror(status)); \ + return status; \ + } \ + } while (0) + +#define CHECKED_DECODE_ONE_FOLLOW(mmdb, offset, entry_data) \ + do { \ + int status = decode_one_follow(mmdb, offset, entry_data); \ + if (MMDB_SUCCESS != status) { \ + DEBUG_MSGF("CHECKED_DECODE_ONE_FOLLOW failed." \ + " status = %d (%s)", status, MMDB_strerror(status)); \ + return status; \ + } \ + } while (0) + +#define FREE_AND_SET_NULL(p) { free((void *)(p)); (p) = NULL; } + +int MMDB_open(const char *const filename, uint32_t flags, MMDB_s *const mmdb) +{ + int status = MMDB_SUCCESS; + + mmdb->file_content = NULL; + mmdb->data_section = NULL; + mmdb->metadata.database_type = NULL; + mmdb->metadata.languages.count = 0; + mmdb->metadata.languages.names = NULL; + mmdb->metadata.description.count = 0; + + mmdb->filename = mmdb_strdup(filename); + if (NULL == mmdb->filename) { + status = MMDB_OUT_OF_MEMORY_ERROR; + goto cleanup; + } + + if ((flags & MMDB_MODE_MASK) == 0) { + flags |= MMDB_MODE_MMAP; + } + mmdb->flags = flags; + + if (MMDB_SUCCESS != (status = map_file(mmdb))) { + goto cleanup; + } + +#ifdef _WIN32 + WSADATA wsa; + WSAStartup(MAKEWORD(2, 2), &wsa); +#endif + + uint32_t metadata_size = 0; + const uint8_t *metadata = find_metadata(mmdb->file_content, mmdb->file_size, + &metadata_size); + if (NULL == metadata) { + status = MMDB_INVALID_METADATA_ERROR; + goto cleanup; + } + + mmdb->metadata_section = metadata; + mmdb->metadata_section_size = metadata_size; + + status = read_metadata(mmdb); + if (MMDB_SUCCESS != status) { + goto cleanup; + } + + if (mmdb->metadata.binary_format_major_version != 2) { + status = MMDB_UNKNOWN_DATABASE_FORMAT_ERROR; + goto cleanup; + } + + uint32_t search_tree_size = mmdb->metadata.node_count * + mmdb->full_record_byte_size; + + mmdb->data_section = mmdb->file_content + search_tree_size + + MMDB_DATA_SECTION_SEPARATOR; + if (search_tree_size + MMDB_DATA_SECTION_SEPARATOR > + (uint32_t)mmdb->file_size) { + status = MMDB_INVALID_METADATA_ERROR; + goto cleanup; + } + mmdb->data_section_size = (uint32_t)mmdb->file_size - search_tree_size - + MMDB_DATA_SECTION_SEPARATOR; + + // Although it is likely not possible to construct a database with valid + // valid metadata, as parsed above, and a data_section_size less than 3, + // we do this check as later we assume it is at least three when doing + // bound checks. + if (mmdb->data_section_size < 3) { + status = MMDB_INVALID_DATA_ERROR; + goto cleanup; + } + + mmdb->metadata_section = metadata; + mmdb->ipv4_start_node.node_value = 0; + mmdb->ipv4_start_node.netmask = 0; + + // We do this immediately as otherwise there is a race to set + // ipv4_start_node.node_value and ipv4_start_node.netmask. + if (mmdb->metadata.ip_version == 6) { + status = find_ipv4_start_node(mmdb); + if (status != MMDB_SUCCESS) { + goto cleanup; + } + } + + cleanup: + if (MMDB_SUCCESS != status) { + int saved_errno = errno; + free_mmdb_struct(mmdb); + errno = saved_errno; + } + return status; +} + +#ifdef _WIN32 + +LOCAL LPWSTR utf8_to_utf16(const char *utf8_str) +{ + int wide_chars = MultiByteToWideChar(CP_UTF8, 0, utf8_str, -1, NULL, 0); + wchar_t *utf16_str = (wchar_t *)malloc(wide_chars * sizeof(wchar_t)); + + if (MultiByteToWideChar(CP_UTF8, 0, utf8_str, -1, utf16_str, + wide_chars) < 1) { + free(utf16_str); + return NULL; + } + + return utf16_str; +} + +LOCAL int map_file(MMDB_s *const mmdb) +{ + DWORD size; + int status = MMDB_SUCCESS; + HANDLE mmh = NULL; + HANDLE fd = INVALID_HANDLE_VALUE; + LPWSTR utf16_filename = utf8_to_utf16(mmdb->filename); + if (!utf16_filename) { + status = MMDB_FILE_OPEN_ERROR; + goto cleanup; + } + fd = CreateFile(utf16_filename, GENERIC_READ, FILE_SHARE_READ, NULL, + OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if (fd == INVALID_HANDLE_VALUE) { + status = MMDB_FILE_OPEN_ERROR; + goto cleanup; + } + size = GetFileSize(fd, NULL); + if (size == INVALID_FILE_SIZE) { + status = MMDB_FILE_OPEN_ERROR; + goto cleanup; + } + mmh = CreateFileMapping(fd, NULL, PAGE_READONLY, 0, size, NULL); + /* Microsoft documentation for CreateFileMapping indicates this returns + NULL not INVALID_HANDLE_VALUE on error */ + if (NULL == mmh) { + status = MMDB_IO_ERROR; + goto cleanup; + } + uint8_t *file_content = + (uint8_t *)MapViewOfFile(mmh, FILE_MAP_READ, 0, 0, 0); + if (file_content == NULL) { + status = MMDB_IO_ERROR; + goto cleanup; + } + + mmdb->file_size = size; + mmdb->file_content = file_content; + + cleanup:; + int saved_errno = errno; + if (INVALID_HANDLE_VALUE != fd) { + CloseHandle(fd); + } + if (NULL != mmh) { + CloseHandle(mmh); + } + errno = saved_errno; + free(utf16_filename); + + return status; +} + +#else // _WIN32 + +LOCAL int map_file(MMDB_s *const mmdb) +{ + ssize_t size; + int status = MMDB_SUCCESS; + + int flags = O_RDONLY; +#ifdef O_CLOEXEC + flags |= O_CLOEXEC; +#endif + int fd = open(mmdb->filename, flags); + struct stat s; + if (fd < 0 || fstat(fd, &s)) { + status = MMDB_FILE_OPEN_ERROR; + goto cleanup; + } + + size = s.st_size; + if (size < 0 || size != s.st_size) { + status = MMDB_OUT_OF_MEMORY_ERROR; + goto cleanup; + } + + uint8_t *file_content = + (uint8_t *)mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0); + if (MAP_FAILED == file_content) { + if (ENOMEM == errno) { + status = MMDB_OUT_OF_MEMORY_ERROR; + } else { + status = MMDB_IO_ERROR; + } + goto cleanup; + } + + mmdb->file_size = size; + mmdb->file_content = file_content; + + cleanup:; + int saved_errno = errno; + if (fd >= 0) { + close(fd); + } + errno = saved_errno; + + return status; +} + +#endif // _WIN32 + +LOCAL const uint8_t *find_metadata(const uint8_t *file_content, + ssize_t file_size, uint32_t *metadata_size) +{ + const ssize_t marker_len = sizeof(METADATA_MARKER) - 1; + ssize_t max_size = file_size > + METADATA_BLOCK_MAX_SIZE ? METADATA_BLOCK_MAX_SIZE : + file_size; + + uint8_t *search_area = (uint8_t *)(file_content + (file_size - max_size)); + uint8_t *start = search_area; + uint8_t *tmp; + do { + tmp = mmdb_memmem(search_area, max_size, + METADATA_MARKER, marker_len); + + if (NULL != tmp) { + max_size -= tmp - search_area; + search_area = tmp; + + /* Continue searching just after the marker we just read, in case + * there are multiple markers in the same file. This would be odd + * but is certainly not impossible. */ + max_size -= marker_len; + search_area += marker_len; + } + } while (NULL != tmp); + + if (search_area == start) { + return NULL; + } + + *metadata_size = (uint32_t)max_size; + + return search_area; +} + +LOCAL int read_metadata(MMDB_s *mmdb) +{ + /* We need to create a fake MMDB_s struct in order to decode values from + the metadata. The metadata is basically just like the data section, so we + want to use the same functions we use for the data section to get metadata + values. */ + MMDB_s metadata_db = make_fake_metadata_db(mmdb); + + MMDB_entry_s metadata_start = { + .mmdb = &metadata_db, + .offset = 0 + }; + + int status = + value_for_key_as_uint32(&metadata_start, "node_count", + &mmdb->metadata.node_count); + if (MMDB_SUCCESS != status) { + return status; + } + if (!mmdb->metadata.node_count) { + DEBUG_MSG("could not find node_count value in metadata"); + return MMDB_INVALID_METADATA_ERROR; + } + + status = value_for_key_as_uint16(&metadata_start, "record_size", + &mmdb->metadata.record_size); + if (MMDB_SUCCESS != status) { + return status; + } + if (!mmdb->metadata.record_size) { + DEBUG_MSG("could not find record_size value in metadata"); + return MMDB_INVALID_METADATA_ERROR; + } + + if (mmdb->metadata.record_size != 24 && mmdb->metadata.record_size != 28 + && mmdb->metadata.record_size != 32) { + DEBUG_MSGF("bad record size in metadata: %i", + mmdb->metadata.record_size); + return MMDB_UNKNOWN_DATABASE_FORMAT_ERROR; + } + + status = value_for_key_as_uint16(&metadata_start, "ip_version", + &mmdb->metadata.ip_version); + if (MMDB_SUCCESS != status) { + return status; + } + if (!mmdb->metadata.ip_version) { + DEBUG_MSG("could not find ip_version value in metadata"); + return MMDB_INVALID_METADATA_ERROR; + } + if (!(mmdb->metadata.ip_version == 4 || mmdb->metadata.ip_version == 6)) { + DEBUG_MSGF("ip_version value in metadata is not 4 or 6 - it was %i", + mmdb->metadata.ip_version); + return MMDB_INVALID_METADATA_ERROR; + } + + status = value_for_key_as_string(&metadata_start, "database_type", + &mmdb->metadata.database_type); + if (MMDB_SUCCESS != status) { + DEBUG_MSG("error finding database_type value in metadata"); + return status; + } + + status = + populate_languages_metadata(mmdb, &metadata_db, &metadata_start); + if (MMDB_SUCCESS != status) { + DEBUG_MSG("could not populate languages from metadata"); + return status; + } + + status = value_for_key_as_uint16( + &metadata_start, "binary_format_major_version", + &mmdb->metadata.binary_format_major_version); + if (MMDB_SUCCESS != status) { + return status; + } + if (!mmdb->metadata.binary_format_major_version) { + DEBUG_MSG( + "could not find binary_format_major_version value in metadata"); + return MMDB_INVALID_METADATA_ERROR; + } + + status = value_for_key_as_uint16( + &metadata_start, "binary_format_minor_version", + &mmdb->metadata.binary_format_minor_version); + if (MMDB_SUCCESS != status) { + return status; + } + + status = value_for_key_as_uint64(&metadata_start, "build_epoch", + &mmdb->metadata.build_epoch); + if (MMDB_SUCCESS != status) { + return status; + } + if (!mmdb->metadata.build_epoch) { + DEBUG_MSG("could not find build_epoch value in metadata"); + return MMDB_INVALID_METADATA_ERROR; + } + + status = populate_description_metadata(mmdb, &metadata_db, &metadata_start); + if (MMDB_SUCCESS != status) { + DEBUG_MSG("could not populate description from metadata"); + return status; + } + + mmdb->full_record_byte_size = mmdb->metadata.record_size * 2 / 8U; + + mmdb->depth = mmdb->metadata.ip_version == 4 ? 32 : 128; + + return MMDB_SUCCESS; +} + +LOCAL MMDB_s make_fake_metadata_db(const MMDB_s *const mmdb) +{ + MMDB_s fake_metadata_db = { + .data_section = mmdb->metadata_section, + .data_section_size = mmdb->metadata_section_size + }; + + return fake_metadata_db; +} + +LOCAL int value_for_key_as_uint16(MMDB_entry_s *start, char *key, + uint16_t *value) +{ + MMDB_entry_data_s entry_data; + const char *path[] = { key, NULL }; + int status = MMDB_aget_value(start, &entry_data, path); + if (MMDB_SUCCESS != status) { + return status; + } + if (MMDB_DATA_TYPE_UINT16 != entry_data.type) { + DEBUG_MSGF("expect uint16 for %s but received %s", key, + type_num_to_name( + entry_data.type)); + return MMDB_INVALID_METADATA_ERROR; + } + *value = entry_data.uint16; + return MMDB_SUCCESS; +} + +LOCAL int value_for_key_as_uint32(MMDB_entry_s *start, char *key, + uint32_t *value) +{ + MMDB_entry_data_s entry_data; + const char *path[] = { key, NULL }; + int status = MMDB_aget_value(start, &entry_data, path); + if (MMDB_SUCCESS != status) { + return status; + } + if (MMDB_DATA_TYPE_UINT32 != entry_data.type) { + DEBUG_MSGF("expect uint32 for %s but received %s", key, + type_num_to_name( + entry_data.type)); + return MMDB_INVALID_METADATA_ERROR; + } + *value = entry_data.uint32; + return MMDB_SUCCESS; +} + +LOCAL int value_for_key_as_uint64(MMDB_entry_s *start, char *key, + uint64_t *value) +{ + MMDB_entry_data_s entry_data; + const char *path[] = { key, NULL }; + int status = MMDB_aget_value(start, &entry_data, path); + if (MMDB_SUCCESS != status) { + return status; + } + if (MMDB_DATA_TYPE_UINT64 != entry_data.type) { + DEBUG_MSGF("expect uint64 for %s but received %s", key, + type_num_to_name( + entry_data.type)); + return MMDB_INVALID_METADATA_ERROR; + } + *value = entry_data.uint64; + return MMDB_SUCCESS; +} + +LOCAL int value_for_key_as_string(MMDB_entry_s *start, char *key, + char const **value) +{ + MMDB_entry_data_s entry_data; + const char *path[] = { key, NULL }; + int status = MMDB_aget_value(start, &entry_data, path); + if (MMDB_SUCCESS != status) { + return status; + } + if (MMDB_DATA_TYPE_UTF8_STRING != entry_data.type) { + DEBUG_MSGF("expect string for %s but received %s", key, + type_num_to_name( + entry_data.type)); + return MMDB_INVALID_METADATA_ERROR; + } + *value = mmdb_strndup((char *)entry_data.utf8_string, entry_data.data_size); + if (NULL == *value) { + return MMDB_OUT_OF_MEMORY_ERROR; + } + return MMDB_SUCCESS; +} + +LOCAL int populate_languages_metadata(MMDB_s *mmdb, MMDB_s *metadata_db, + MMDB_entry_s *metadata_start) +{ + MMDB_entry_data_s entry_data; + + const char *path[] = { "languages", NULL }; + int status = MMDB_aget_value(metadata_start, &entry_data, path); + if (MMDB_SUCCESS != status) { + return status; + } + if (MMDB_DATA_TYPE_ARRAY != entry_data.type) { + return MMDB_INVALID_METADATA_ERROR; + } + + MMDB_entry_s array_start = { + .mmdb = metadata_db, + .offset = entry_data.offset + }; + + MMDB_entry_data_list_s *member; + status = MMDB_get_entry_data_list(&array_start, &member); + if (MMDB_SUCCESS != status) { + return status; + } + + MMDB_entry_data_list_s *first_member = member; + + uint32_t array_size = member->entry_data.data_size; + MAYBE_CHECK_SIZE_OVERFLOW(array_size, SIZE_MAX / sizeof(char *), + MMDB_INVALID_METADATA_ERROR); + + mmdb->metadata.languages.count = 0; + mmdb->metadata.languages.names = malloc(array_size * sizeof(char *)); + if (NULL == mmdb->metadata.languages.names) { + return MMDB_OUT_OF_MEMORY_ERROR; + } + + for (uint32_t i = 0; i < array_size; i++) { + member = member->next; + if (MMDB_DATA_TYPE_UTF8_STRING != member->entry_data.type) { + return MMDB_INVALID_METADATA_ERROR; + } + + mmdb->metadata.languages.names[i] = + mmdb_strndup((char *)member->entry_data.utf8_string, + member->entry_data.data_size); + + if (NULL == mmdb->metadata.languages.names[i]) { + return MMDB_OUT_OF_MEMORY_ERROR; + } + // We assign this as we go so that if we fail a malloc and need to + // free it, the count is right. + mmdb->metadata.languages.count = i + 1; + } + + MMDB_free_entry_data_list(first_member); + + return MMDB_SUCCESS; +} + +LOCAL int populate_description_metadata(MMDB_s *mmdb, MMDB_s *metadata_db, + MMDB_entry_s *metadata_start) +{ + MMDB_entry_data_s entry_data; + + const char *path[] = { "description", NULL }; + int status = MMDB_aget_value(metadata_start, &entry_data, path); + if (MMDB_SUCCESS != status) { + return status; + } + + if (MMDB_DATA_TYPE_MAP != entry_data.type) { + DEBUG_MSGF("Unexpected entry_data type: %d", entry_data.type); + return MMDB_INVALID_METADATA_ERROR; + } + + MMDB_entry_s map_start = { + .mmdb = metadata_db, + .offset = entry_data.offset + }; + + MMDB_entry_data_list_s *member; + status = MMDB_get_entry_data_list(&map_start, &member); + if (MMDB_SUCCESS != status) { + DEBUG_MSGF( + "MMDB_get_entry_data_list failed while populating description." + " status = %d (%s)", status, MMDB_strerror(status)); + return status; + } + + MMDB_entry_data_list_s *first_member = member; + + uint32_t map_size = member->entry_data.data_size; + mmdb->metadata.description.count = 0; + if (0 == map_size) { + mmdb->metadata.description.descriptions = NULL; + goto cleanup; + } + MAYBE_CHECK_SIZE_OVERFLOW(map_size, SIZE_MAX / sizeof(MMDB_description_s *), + MMDB_INVALID_METADATA_ERROR); + + mmdb->metadata.description.descriptions = + malloc(map_size * sizeof(MMDB_description_s *)); + if (NULL == mmdb->metadata.description.descriptions) { + status = MMDB_OUT_OF_MEMORY_ERROR; + goto cleanup; + } + + for (uint32_t i = 0; i < map_size; i++) { + mmdb->metadata.description.descriptions[i] = + malloc(sizeof(MMDB_description_s)); + if (NULL == mmdb->metadata.description.descriptions[i]) { + status = MMDB_OUT_OF_MEMORY_ERROR; + goto cleanup; + } + + mmdb->metadata.description.count = i + 1; + mmdb->metadata.description.descriptions[i]->language = NULL; + mmdb->metadata.description.descriptions[i]->description = NULL; + + member = member->next; + + if (MMDB_DATA_TYPE_UTF8_STRING != member->entry_data.type) { + status = MMDB_INVALID_METADATA_ERROR; + goto cleanup; + } + + mmdb->metadata.description.descriptions[i]->language = + mmdb_strndup((char *)member->entry_data.utf8_string, + member->entry_data.data_size); + + if (NULL == mmdb->metadata.description.descriptions[i]->language) { + status = MMDB_OUT_OF_MEMORY_ERROR; + goto cleanup; + } + + member = member->next; + + if (MMDB_DATA_TYPE_UTF8_STRING != member->entry_data.type) { + status = MMDB_INVALID_METADATA_ERROR; + goto cleanup; + } + + mmdb->metadata.description.descriptions[i]->description = + mmdb_strndup((char *)member->entry_data.utf8_string, + member->entry_data.data_size); + + if (NULL == mmdb->metadata.description.descriptions[i]->description) { + status = MMDB_OUT_OF_MEMORY_ERROR; + goto cleanup; + } + } + + cleanup: + MMDB_free_entry_data_list(first_member); + + return status; +} + +MMDB_lookup_result_s MMDB_lookup_string(const MMDB_s *const mmdb, + const char *const ipstr, + int *const gai_error, + int *const mmdb_error) +{ + MMDB_lookup_result_s result = { + .found_entry = false, + .netmask = 0, + .entry = { + .mmdb = mmdb, + .offset = 0 + } + }; + + struct addrinfo *addresses = NULL; + *gai_error = resolve_any_address(ipstr, &addresses); + + if (!*gai_error) { + result = MMDB_lookup_sockaddr(mmdb, addresses->ai_addr, mmdb_error); + } + + if (NULL != addresses) { + freeaddrinfo(addresses); + } + + return result; +} + +LOCAL int resolve_any_address(const char *ipstr, struct addrinfo **addresses) +{ + struct addrinfo hints = { + .ai_family = AF_UNSPEC, + .ai_flags = AI_NUMERICHOST, + // We set ai_socktype so that we only get one result back + .ai_socktype = SOCK_STREAM + }; + + int gai_status = getaddrinfo(ipstr, NULL, &hints, addresses); + if (gai_status) { + return gai_status; + } + + return 0; +} + +MMDB_lookup_result_s MMDB_lookup_sockaddr( + const MMDB_s *const mmdb, + const struct sockaddr *const sockaddr, + int *const mmdb_error) +{ + MMDB_lookup_result_s result = { + .found_entry = false, + .netmask = 0, + .entry = { + .mmdb = mmdb, + .offset = 0 + } + }; + + uint8_t mapped_address[16], *address; + if (mmdb->metadata.ip_version == 4) { + if (sockaddr->sa_family == AF_INET6) { + *mmdb_error = MMDB_IPV6_LOOKUP_IN_IPV4_DATABASE_ERROR; + return result; + } + address = (uint8_t *)&((struct sockaddr_in *)sockaddr)->sin_addr.s_addr; + } else { + if (sockaddr->sa_family == AF_INET6) { + address = + (uint8_t *)&((struct sockaddr_in6 *)sockaddr)->sin6_addr. + s6_addr; + } else { + address = mapped_address; + memset(address, 0, 12); + memcpy(address + 12, + &((struct sockaddr_in *)sockaddr)->sin_addr.s_addr, 4); + } + } + + *mmdb_error = + find_address_in_search_tree(mmdb, address, sockaddr->sa_family, + &result); + + return result; +} + +LOCAL int find_address_in_search_tree(const MMDB_s *const mmdb, + uint8_t *address, + sa_family_t address_family, + MMDB_lookup_result_s *result) +{ + record_info_s record_info = record_info_for_database(mmdb); + if (0 == record_info.right_record_offset) { + return MMDB_UNKNOWN_DATABASE_FORMAT_ERROR; + } + + uint32_t value = 0; + uint16_t current_bit = 0; + if (mmdb->metadata.ip_version == 6 && address_family == AF_INET) { + value = mmdb->ipv4_start_node.node_value; + current_bit = mmdb->ipv4_start_node.netmask; + } + + uint32_t node_count = mmdb->metadata.node_count; + const uint8_t *search_tree = mmdb->file_content; + const uint8_t *record_pointer; + for (; current_bit < mmdb->depth && value < node_count; current_bit++) { + uint8_t bit = 1U & + (address[current_bit >> 3] >> (7 - (current_bit % 8))); + + record_pointer = &search_tree[value * record_info.record_length]; + if (record_pointer + record_info.record_length > mmdb->data_section) { + return MMDB_CORRUPT_SEARCH_TREE_ERROR; + } + if (bit) { + record_pointer += record_info.right_record_offset; + value = record_info.right_record_getter(record_pointer); + } else { + value = record_info.left_record_getter(record_pointer); + } + } + + result->netmask = current_bit; + + if (value >= node_count + mmdb->data_section_size) { + // The pointer points off the end of the database. + return MMDB_CORRUPT_SEARCH_TREE_ERROR; + } + + if (value == node_count) { + // record is empty + result->found_entry = false; + return MMDB_SUCCESS; + } + result->found_entry = true; + result->entry.offset = data_section_offset_for_record(mmdb, value); + + return MMDB_SUCCESS; +} + +LOCAL record_info_s record_info_for_database(const MMDB_s *const mmdb) +{ + record_info_s record_info = { + .record_length = mmdb->full_record_byte_size, + .right_record_offset = 0 + }; + + if (record_info.record_length == 6) { + record_info.left_record_getter = &get_uint24; + record_info.right_record_getter = &get_uint24; + record_info.right_record_offset = 3; + } else if (record_info.record_length == 7) { + record_info.left_record_getter = &get_left_28_bit_record; + record_info.right_record_getter = &get_right_28_bit_record; + record_info.right_record_offset = 3; + } else if (record_info.record_length == 8) { + record_info.left_record_getter = &get_uint32; + record_info.right_record_getter = &get_uint32; + record_info.right_record_offset = 4; + } else { + assert(false); + } + + return record_info; +} + +LOCAL int find_ipv4_start_node(MMDB_s *const mmdb) +{ + /* In a pathological case of a database with a single node search tree, + * this check will be true even after we've found the IPv4 start node, but + * that doesn't seem worth trying to fix. */ + if (mmdb->ipv4_start_node.node_value != 0) { + return MMDB_SUCCESS; + } + + record_info_s record_info = record_info_for_database(mmdb); + + const uint8_t *search_tree = mmdb->file_content; + uint32_t node_value = 0; + const uint8_t *record_pointer; + uint16_t netmask; + uint32_t node_count = mmdb->metadata.node_count; + + for (netmask = 0; netmask < 96 && node_value < node_count; netmask++) { + record_pointer = &search_tree[node_value * record_info.record_length]; + if (record_pointer + record_info.record_length > mmdb->data_section) { + return MMDB_CORRUPT_SEARCH_TREE_ERROR; + } + node_value = record_info.left_record_getter(record_pointer); + } + + mmdb->ipv4_start_node.node_value = node_value; + mmdb->ipv4_start_node.netmask = netmask; + + return MMDB_SUCCESS; +} + +LOCAL uint8_t record_type(const MMDB_s *const mmdb, uint64_t record) +{ + uint32_t node_count = mmdb->metadata.node_count; + + /* Ideally we'd check to make sure that a record never points to a + * previously seen value, but that's more complicated. For now, we can + * at least check that we don't end up at the top of the tree again. */ + if (record == 0) { + DEBUG_MSG("record has a value of 0"); + return MMDB_RECORD_TYPE_INVALID; + } + + if (record < node_count) { + return MMDB_RECORD_TYPE_SEARCH_NODE; + } + + if (record == node_count) { + return MMDB_RECORD_TYPE_EMPTY; + } + + if (record - node_count < mmdb->data_section_size) { + return MMDB_RECORD_TYPE_DATA; + } + + DEBUG_MSG("record has a value that points outside of the database"); + return MMDB_RECORD_TYPE_INVALID; +} + +LOCAL uint32_t get_left_28_bit_record(const uint8_t *record) +{ + return record[0] * 65536 + record[1] * 256 + record[2] + + ((record[3] & 0xf0) << 20); +} + +LOCAL uint32_t get_right_28_bit_record(const uint8_t *record) +{ + uint32_t value = get_uint32(record); + return value & 0xfffffff; +} + +int MMDB_read_node(const MMDB_s *const mmdb, uint32_t node_number, + MMDB_search_node_s *const node) +{ + record_info_s record_info = record_info_for_database(mmdb); + if (0 == record_info.right_record_offset) { + return MMDB_UNKNOWN_DATABASE_FORMAT_ERROR; + } + + if (node_number > mmdb->metadata.node_count) { + return MMDB_INVALID_NODE_NUMBER_ERROR; + } + + const uint8_t *search_tree = mmdb->file_content; + const uint8_t *record_pointer = + &search_tree[node_number * record_info.record_length]; + node->left_record = record_info.left_record_getter(record_pointer); + record_pointer += record_info.right_record_offset; + node->right_record = record_info.right_record_getter(record_pointer); + + node->left_record_type = record_type(mmdb, node->left_record); + node->right_record_type = record_type(mmdb, node->right_record); + + // Note that offset will be invalid if the record type is not + // MMDB_RECORD_TYPE_DATA, but that's ok. Any use of the record entry + // for other data types is a programming error. + node->left_record_entry = (struct MMDB_entry_s) { + .mmdb = mmdb, + .offset = data_section_offset_for_record(mmdb, node->left_record), + }; + node->right_record_entry = (struct MMDB_entry_s) { + .mmdb = mmdb, + .offset = data_section_offset_for_record(mmdb, node->right_record), + }; + + return MMDB_SUCCESS; +} + +LOCAL uint32_t data_section_offset_for_record(const MMDB_s *const mmdb, + uint64_t record) +{ + return (uint32_t)record - mmdb->metadata.node_count - + MMDB_DATA_SECTION_SEPARATOR; +} + +int MMDB_get_value(MMDB_entry_s *const start, + MMDB_entry_data_s *const entry_data, + ...) +{ + va_list path; + va_start(path, entry_data); + int status = MMDB_vget_value(start, entry_data, path); + va_end(path); + return status; +} + +int MMDB_vget_value(MMDB_entry_s *const start, + MMDB_entry_data_s *const entry_data, + va_list va_path) +{ + int length = path_length(va_path); + const char *path_elem; + int i = 0; + + MAYBE_CHECK_SIZE_OVERFLOW(length, SIZE_MAX / sizeof(const char *) - 1, + MMDB_INVALID_METADATA_ERROR); + + const char **path = malloc((length + 1) * sizeof(const char *)); + if (NULL == path) { + return MMDB_OUT_OF_MEMORY_ERROR; + } + + while (NULL != (path_elem = va_arg(va_path, char *))) { + path[i] = path_elem; + i++; + } + path[i] = NULL; + + int status = MMDB_aget_value(start, entry_data, path); + + free((char **)path); + + return status; +} + +LOCAL int path_length(va_list va_path) +{ + int i = 0; + const char *ignore; + va_list path_copy; + va_copy(path_copy, va_path); + + while (NULL != (ignore = va_arg(path_copy, char *))) { + i++; + } + + va_end(path_copy); + + return i; +} + +int MMDB_aget_value(MMDB_entry_s *const start, + MMDB_entry_data_s *const entry_data, + const char *const *const path) +{ + const MMDB_s *const mmdb = start->mmdb; + uint32_t offset = start->offset; + + memset(entry_data, 0, sizeof(MMDB_entry_data_s)); + DEBUG_NL; + DEBUG_MSG("looking up value by path"); + + CHECKED_DECODE_ONE_FOLLOW(mmdb, offset, entry_data); + + DEBUG_NL; + DEBUG_MSGF("top level element is a %s", type_num_to_name(entry_data->type)); + + /* Can this happen? It'd probably represent a pathological case under + * normal use, but there's nothing preventing someone from passing an + * invalid MMDB_entry_s struct to this function */ + if (!entry_data->has_data) { + return MMDB_INVALID_LOOKUP_PATH_ERROR; + } + + const char *path_elem; + int i = 0; + while (NULL != (path_elem = path[i++])) { + DEBUG_NL; + DEBUG_MSGF("path elem = %s", path_elem); + + /* XXX - it'd be good to find a quicker way to skip through these + entries that doesn't involve decoding them + completely. Basically we need to just use the size from the + control byte to advance our pointer rather than calling + decode_one(). */ + if (entry_data->type == MMDB_DATA_TYPE_ARRAY) { + int status = lookup_path_in_array(path_elem, mmdb, entry_data); + if (MMDB_SUCCESS != status) { + memset(entry_data, 0, sizeof(MMDB_entry_data_s)); + return status; + } + } else if (entry_data->type == MMDB_DATA_TYPE_MAP) { + int status = lookup_path_in_map(path_elem, mmdb, entry_data); + if (MMDB_SUCCESS != status) { + memset(entry_data, 0, sizeof(MMDB_entry_data_s)); + return status; + } + } else { + /* Once we make the code traverse maps & arrays without calling + * decode_one() we can get rid of this. */ + memset(entry_data, 0, sizeof(MMDB_entry_data_s)); + return MMDB_LOOKUP_PATH_DOES_NOT_MATCH_DATA_ERROR; + } + } + + return MMDB_SUCCESS; +} + +LOCAL int lookup_path_in_array(const char *path_elem, + const MMDB_s *const mmdb, + MMDB_entry_data_s *entry_data) +{ + uint32_t size = entry_data->data_size; + char *first_invalid; + + int saved_errno = errno; + errno = 0; + int array_index = strtol(path_elem, &first_invalid, 10); + if (ERANGE == errno) { + errno = saved_errno; + return MMDB_INVALID_LOOKUP_PATH_ERROR; + } + errno = saved_errno; + + if (array_index < 0) { + array_index += size; + + if (array_index < 0) { + return MMDB_LOOKUP_PATH_DOES_NOT_MATCH_DATA_ERROR; + } + } + + if (*first_invalid || (uint32_t)array_index >= size) { + return MMDB_LOOKUP_PATH_DOES_NOT_MATCH_DATA_ERROR; + } + + for (int i = 0; i < array_index; i++) { + /* We don't want to follow a pointer here. If the next element is a + * pointer we simply skip it and keep going */ + CHECKED_DECODE_ONE(mmdb, entry_data->offset_to_next, entry_data); + int status = skip_map_or_array(mmdb, entry_data); + if (MMDB_SUCCESS != status) { + return status; + } + } + + MMDB_entry_data_s value; + CHECKED_DECODE_ONE_FOLLOW(mmdb, entry_data->offset_to_next, &value); + memcpy(entry_data, &value, sizeof(MMDB_entry_data_s)); + + return MMDB_SUCCESS; +} + +LOCAL int lookup_path_in_map(const char *path_elem, + const MMDB_s *const mmdb, + MMDB_entry_data_s *entry_data) +{ + uint32_t size = entry_data->data_size; + uint32_t offset = entry_data->offset_to_next; + size_t path_elem_len = strlen(path_elem); + + while (size-- > 0) { + MMDB_entry_data_s key, value; + CHECKED_DECODE_ONE_FOLLOW(mmdb, offset, &key); + + uint32_t offset_to_value = key.offset_to_next; + + if (MMDB_DATA_TYPE_UTF8_STRING != key.type) { + return MMDB_INVALID_DATA_ERROR; + } + + if (key.data_size == path_elem_len && + !memcmp(path_elem, key.utf8_string, path_elem_len)) { + + DEBUG_MSG("found key matching path elem"); + + CHECKED_DECODE_ONE_FOLLOW(mmdb, offset_to_value, &value); + memcpy(entry_data, &value, sizeof(MMDB_entry_data_s)); + return MMDB_SUCCESS; + } else { + /* We don't want to follow a pointer here. If the next element is + * a pointer we simply skip it and keep going */ + CHECKED_DECODE_ONE(mmdb, offset_to_value, &value); + int status = skip_map_or_array(mmdb, &value); + if (MMDB_SUCCESS != status) { + return status; + } + offset = value.offset_to_next; + } + } + + memset(entry_data, 0, sizeof(MMDB_entry_data_s)); + return MMDB_LOOKUP_PATH_DOES_NOT_MATCH_DATA_ERROR; +} + +LOCAL int skip_map_or_array(const MMDB_s *const mmdb, + MMDB_entry_data_s *entry_data) +{ + if (entry_data->type == MMDB_DATA_TYPE_MAP) { + uint32_t size = entry_data->data_size; + while (size-- > 0) { + CHECKED_DECODE_ONE(mmdb, entry_data->offset_to_next, entry_data); // key + CHECKED_DECODE_ONE(mmdb, entry_data->offset_to_next, entry_data); // value + int status = skip_map_or_array(mmdb, entry_data); + if (MMDB_SUCCESS != status) { + return status; + } + } + } else if (entry_data->type == MMDB_DATA_TYPE_ARRAY) { + uint32_t size = entry_data->data_size; + while (size-- > 0) { + CHECKED_DECODE_ONE(mmdb, entry_data->offset_to_next, entry_data); // value + int status = skip_map_or_array(mmdb, entry_data); + if (MMDB_SUCCESS != status) { + return status; + } + } + } + + return MMDB_SUCCESS; +} + +LOCAL int decode_one_follow(const MMDB_s *const mmdb, uint32_t offset, + MMDB_entry_data_s *entry_data) +{ + CHECKED_DECODE_ONE(mmdb, offset, entry_data); + if (entry_data->type == MMDB_DATA_TYPE_POINTER) { + uint32_t next = entry_data->offset_to_next; + CHECKED_DECODE_ONE(mmdb, entry_data->pointer, entry_data); + /* Pointers to pointers are illegal under the spec */ + if (entry_data->type == MMDB_DATA_TYPE_POINTER) { + DEBUG_MSG("pointer points to another pointer"); + return MMDB_INVALID_DATA_ERROR; + } + + /* The pointer could point to any part of the data section but the + * next entry for this particular offset may be the one after the + * pointer, not the one after whatever the pointer points to. This + * depends on whether the pointer points to something that is a simple + * value or a compound value. For a compound value, the next one is + * the one after the pointer result, not the one after the pointer. */ + if (entry_data->type != MMDB_DATA_TYPE_MAP + && entry_data->type != MMDB_DATA_TYPE_ARRAY) { + + entry_data->offset_to_next = next; + } + } + + return MMDB_SUCCESS; +} + +#if !MMDB_UINT128_IS_BYTE_ARRAY +LOCAL mmdb_uint128_t get_uint128(const uint8_t *p, int length) +{ + mmdb_uint128_t value = 0; + while (length-- > 0) { + value <<= 8; + value += *p++; + } + return value; +} +#endif + +LOCAL int decode_one(const MMDB_s *const mmdb, uint32_t offset, + MMDB_entry_data_s *entry_data) +{ + const uint8_t *mem = mmdb->data_section; + + // We subtract rather than add as it possible that offset + 1 + // could overflow for a corrupt database while an underflow + // from data_section_size - 1 should not be possible. + if (offset > mmdb->data_section_size - 1) { + DEBUG_MSGF("Offset (%d) past data section (%d)", offset, + mmdb->data_section_size); + return MMDB_INVALID_DATA_ERROR; + } + + entry_data->offset = offset; + entry_data->has_data = true; + + DEBUG_NL; + DEBUG_MSGF("Offset: %i", offset); + + uint8_t ctrl = mem[offset++]; + DEBUG_BINARY("Control byte: %s", ctrl); + + int type = (ctrl >> 5) & 7; + DEBUG_MSGF("Type: %i (%s)", type, type_num_to_name(type)); + + if (type == MMDB_DATA_TYPE_EXTENDED) { + // Subtracting 1 to avoid possible overflow on offset + 1 + if (offset > mmdb->data_section_size - 1) { + DEBUG_MSGF("Extended type offset (%d) past data section (%d)", + offset, + mmdb->data_section_size); + return MMDB_INVALID_DATA_ERROR; + } + type = get_ext_type(mem[offset++]); + DEBUG_MSGF("Extended type: %i (%s)", type, type_num_to_name(type)); + } + + entry_data->type = type; + + if (type == MMDB_DATA_TYPE_POINTER) { + uint8_t psize = ((ctrl >> 3) & 3) + 1; + DEBUG_MSGF("Pointer size: %i", psize); + + // We check that the offset does not extend past the end of the + // database and that the subtraction of psize did not underflow. + if (offset > mmdb->data_section_size - psize || + mmdb->data_section_size < psize) { + DEBUG_MSGF("Pointer offset (%d) past data section (%d)", offset + + psize, + mmdb->data_section_size); + return MMDB_INVALID_DATA_ERROR; + } + entry_data->pointer = get_ptr_from(ctrl, &mem[offset], psize); + DEBUG_MSGF("Pointer to: %i", entry_data->pointer); + + entry_data->data_size = psize; + entry_data->offset_to_next = offset + psize; + return MMDB_SUCCESS; + } + + uint32_t size = ctrl & 31; + switch (size) { + case 29: + // We subtract when checking offset to avoid possible overflow + if (offset > mmdb->data_section_size - 1) { + DEBUG_MSGF("String end (%d, case 29) past data section (%d)", + offset, + mmdb->data_section_size); + return MMDB_INVALID_DATA_ERROR; + } + size = 29 + mem[offset++]; + break; + case 30: + // We subtract when checking offset to avoid possible overflow + if (offset > mmdb->data_section_size - 2) { + DEBUG_MSGF("String end (%d, case 30) past data section (%d)", + offset, + mmdb->data_section_size); + return MMDB_INVALID_DATA_ERROR; + } + size = 285 + get_uint16(&mem[offset]); + offset += 2; + break; + case 31: + // We subtract when checking offset to avoid possible overflow + if (offset > mmdb->data_section_size - 3) { + DEBUG_MSGF("String end (%d, case 31) past data section (%d)", + offset, + mmdb->data_section_size); + return MMDB_INVALID_DATA_ERROR; + } + size = 65821 + get_uint24(&mem[offset]); + offset += 3; + default: + break; + } + + DEBUG_MSGF("Size: %i", size); + + if (type == MMDB_DATA_TYPE_MAP || type == MMDB_DATA_TYPE_ARRAY) { + entry_data->data_size = size; + entry_data->offset_to_next = offset; + return MMDB_SUCCESS; + } + + if (type == MMDB_DATA_TYPE_BOOLEAN) { + entry_data->boolean = size ? true : false; + entry_data->data_size = 0; + entry_data->offset_to_next = offset; + DEBUG_MSGF("boolean value: %s", entry_data->boolean ? "true" : "false"); + return MMDB_SUCCESS; + } + + // Check that the data doesn't extend past the end of the memory + // buffer and that the calculation in doing this did not underflow. + if (offset > mmdb->data_section_size - size || + mmdb->data_section_size < size) { + DEBUG_MSGF("Data end (%d) past data section (%d)", offset + size, + mmdb->data_section_size); + return MMDB_INVALID_DATA_ERROR; + } + + if (type == MMDB_DATA_TYPE_UINT16) { + if (size > 2) { + DEBUG_MSGF("uint16 of size %d", size); + return MMDB_INVALID_DATA_ERROR; + } + entry_data->uint16 = (uint16_t)get_uintX(&mem[offset], size); + DEBUG_MSGF("uint16 value: %u", entry_data->uint16); + } else if (type == MMDB_DATA_TYPE_UINT32) { + if (size > 4) { + DEBUG_MSGF("uint32 of size %d", size); + return MMDB_INVALID_DATA_ERROR; + } + entry_data->uint32 = (uint32_t)get_uintX(&mem[offset], size); + DEBUG_MSGF("uint32 value: %u", entry_data->uint32); + } else if (type == MMDB_DATA_TYPE_INT32) { + if (size > 4) { + DEBUG_MSGF("int32 of size %d", size); + return MMDB_INVALID_DATA_ERROR; + } + entry_data->int32 = get_sintX(&mem[offset], size); + DEBUG_MSGF("int32 value: %i", entry_data->int32); + } else if (type == MMDB_DATA_TYPE_UINT64) { + if (size > 8) { + DEBUG_MSGF("uint64 of size %d", size); + return MMDB_INVALID_DATA_ERROR; + } + entry_data->uint64 = get_uintX(&mem[offset], size); + DEBUG_MSGF("uint64 value: %" PRIu64, entry_data->uint64); + } else if (type == MMDB_DATA_TYPE_UINT128) { + if (size > 16) { + DEBUG_MSGF("uint128 of size %d", size); + return MMDB_INVALID_DATA_ERROR; + } +#if MMDB_UINT128_IS_BYTE_ARRAY + memset(entry_data->uint128, 0, 16); + if (size > 0) { + memcpy(entry_data->uint128 + 16 - size, &mem[offset], size); + } +#else + entry_data->uint128 = get_uint128(&mem[offset], size); +#endif + } else if (type == MMDB_DATA_TYPE_FLOAT) { + if (size != 4) { + DEBUG_MSGF("float of size %d", size); + return MMDB_INVALID_DATA_ERROR; + } + size = 4; + entry_data->float_value = get_ieee754_float(&mem[offset]); + DEBUG_MSGF("float value: %f", entry_data->float_value); + } else if (type == MMDB_DATA_TYPE_DOUBLE) { + if (size != 8) { + DEBUG_MSGF("double of size %d", size); + return MMDB_INVALID_DATA_ERROR; + } + size = 8; + entry_data->double_value = get_ieee754_double(&mem[offset]); + DEBUG_MSGF("double value: %f", entry_data->double_value); + } else if (type == MMDB_DATA_TYPE_UTF8_STRING) { + entry_data->utf8_string = size == 0 ? "" : (char *)&mem[offset]; + entry_data->data_size = size; +#ifdef MMDB_DEBUG + char *string = mmdb_strndup(entry_data->utf8_string, + size > 50 ? 50 : size); + if (NULL == string) { + abort(); + } + DEBUG_MSGF("string value: %s", string); + free(string); +#endif + } else if (type == MMDB_DATA_TYPE_BYTES) { + entry_data->bytes = &mem[offset]; + entry_data->data_size = size; + } + + entry_data->offset_to_next = offset + size; + + return MMDB_SUCCESS; +} + +LOCAL int get_ext_type(int raw_ext_type) +{ + return 7 + raw_ext_type; +} + +LOCAL uint32_t get_ptr_from(uint8_t ctrl, uint8_t const *const ptr, + int ptr_size) +{ + uint32_t new_offset; + switch (ptr_size) { + case 1: + new_offset = ( (ctrl & 7) << 8) + ptr[0]; + break; + case 2: + new_offset = 2048 + ( (ctrl & 7) << 16 ) + ( ptr[0] << 8) + ptr[1]; + break; + case 3: + new_offset = 2048 + 524288 + ( (ctrl & 7) << 24 ) + get_uint24(ptr); + break; + case 4: + default: + new_offset = get_uint32(ptr); + break; + } + return new_offset; +} + +int MMDB_get_metadata_as_entry_data_list( + const MMDB_s *const mmdb, MMDB_entry_data_list_s **const entry_data_list) +{ + MMDB_s metadata_db = make_fake_metadata_db(mmdb); + + MMDB_entry_s metadata_start = { + .mmdb = &metadata_db, + .offset = 0 + }; + + return MMDB_get_entry_data_list(&metadata_start, entry_data_list); +} + +int MMDB_get_entry_data_list( + MMDB_entry_s *start, MMDB_entry_data_list_s **const entry_data_list) +{ + MMDB_data_pool_s *const pool = data_pool_new(MMDB_POOL_INIT_SIZE); + if (!pool) { + return MMDB_OUT_OF_MEMORY_ERROR; + } + + MMDB_entry_data_list_s *const list = data_pool_alloc(pool); + if (!list) { + data_pool_destroy(pool); + return MMDB_OUT_OF_MEMORY_ERROR; + } + + int const status = get_entry_data_list(start->mmdb, start->offset, list, + pool, 0); + + *entry_data_list = data_pool_to_list(pool); + if (!*entry_data_list) { + data_pool_destroy(pool); + return MMDB_OUT_OF_MEMORY_ERROR; + } + + return status; +} + +LOCAL int get_entry_data_list(const MMDB_s *const mmdb, + uint32_t offset, + MMDB_entry_data_list_s *const entry_data_list, + MMDB_data_pool_s *const pool, + int depth) +{ + if (depth >= MAXIMUM_DATA_STRUCTURE_DEPTH) { + DEBUG_MSG("reached the maximum data structure depth"); + return MMDB_INVALID_DATA_ERROR; + } + depth++; + CHECKED_DECODE_ONE(mmdb, offset, &entry_data_list->entry_data); + + switch (entry_data_list->entry_data.type) { + case MMDB_DATA_TYPE_POINTER: + { + uint32_t next_offset = entry_data_list->entry_data.offset_to_next; + uint32_t last_offset; + CHECKED_DECODE_ONE(mmdb, last_offset = + entry_data_list->entry_data.pointer, + &entry_data_list->entry_data); + + /* Pointers to pointers are illegal under the spec */ + if (entry_data_list->entry_data.type == MMDB_DATA_TYPE_POINTER) { + DEBUG_MSG("pointer points to another pointer"); + return MMDB_INVALID_DATA_ERROR; + } + + if (entry_data_list->entry_data.type == MMDB_DATA_TYPE_ARRAY + || entry_data_list->entry_data.type == MMDB_DATA_TYPE_MAP) { + + int status = + get_entry_data_list(mmdb, last_offset, entry_data_list, + pool, depth); + if (MMDB_SUCCESS != status) { + DEBUG_MSG("get_entry_data_list on pointer failed."); + return status; + } + } + entry_data_list->entry_data.offset_to_next = next_offset; + } + break; + case MMDB_DATA_TYPE_ARRAY: + { + uint32_t array_size = entry_data_list->entry_data.data_size; + uint32_t array_offset = entry_data_list->entry_data.offset_to_next; + while (array_size-- > 0) { + MMDB_entry_data_list_s *entry_data_list_to = + data_pool_alloc(pool); + if (!entry_data_list_to) { + return MMDB_OUT_OF_MEMORY_ERROR; + } + + int status = + get_entry_data_list(mmdb, array_offset, entry_data_list_to, + pool, depth); + if (MMDB_SUCCESS != status) { + DEBUG_MSG("get_entry_data_list on array element failed."); + return status; + } + + array_offset = entry_data_list_to->entry_data.offset_to_next; + } + entry_data_list->entry_data.offset_to_next = array_offset; + + } + break; + case MMDB_DATA_TYPE_MAP: + { + uint32_t size = entry_data_list->entry_data.data_size; + + offset = entry_data_list->entry_data.offset_to_next; + while (size-- > 0) { + MMDB_entry_data_list_s *list_key = data_pool_alloc(pool); + if (!list_key) { + return MMDB_OUT_OF_MEMORY_ERROR; + } + + int status = + get_entry_data_list(mmdb, offset, list_key, pool, depth); + if (MMDB_SUCCESS != status) { + DEBUG_MSG("get_entry_data_list on map key failed."); + return status; + } + + offset = list_key->entry_data.offset_to_next; + + MMDB_entry_data_list_s *list_value = data_pool_alloc(pool); + if (!list_value) { + return MMDB_OUT_OF_MEMORY_ERROR; + } + + status = get_entry_data_list(mmdb, offset, list_value, pool, + depth); + if (MMDB_SUCCESS != status) { + DEBUG_MSG("get_entry_data_list on map element failed."); + return status; + } + offset = list_value->entry_data.offset_to_next; + } + entry_data_list->entry_data.offset_to_next = offset; + } + break; + default: + break; + } + + return MMDB_SUCCESS; +} + +LOCAL float get_ieee754_float(const uint8_t *restrict p) +{ + volatile float f; + uint8_t *q = (void *)&f; +/* Windows builds don't use autoconf but we can assume they're all + * little-endian. */ +#if MMDB_LITTLE_ENDIAN || _WIN32 + q[3] = p[0]; + q[2] = p[1]; + q[1] = p[2]; + q[0] = p[3]; +#else + memcpy(q, p, 4); +#endif + return f; +} + +LOCAL double get_ieee754_double(const uint8_t *restrict p) +{ + volatile double d; + uint8_t *q = (void *)&d; +#if MMDB_LITTLE_ENDIAN || _WIN32 + q[7] = p[0]; + q[6] = p[1]; + q[5] = p[2]; + q[4] = p[3]; + q[3] = p[4]; + q[2] = p[5]; + q[1] = p[6]; + q[0] = p[7]; +#else + memcpy(q, p, 8); +#endif + + return d; +} + +LOCAL uint32_t get_uint32(const uint8_t *p) +{ + return p[0] * 16777216U + p[1] * 65536 + p[2] * 256 + p[3]; +} + +LOCAL uint32_t get_uint24(const uint8_t *p) +{ + return p[0] * 65536U + p[1] * 256 + p[2]; +} + +LOCAL uint32_t get_uint16(const uint8_t *p) +{ + return p[0] * 256U + p[1]; +} + +LOCAL uint64_t get_uintX(const uint8_t *p, int length) +{ + uint64_t value = 0; + while (length-- > 0) { + value <<= 8; + value += *p++; + } + return value; +} + +LOCAL int32_t get_sintX(const uint8_t *p, int length) +{ + return (int32_t)get_uintX(p, length); +} + +void MMDB_free_entry_data_list(MMDB_entry_data_list_s *const entry_data_list) +{ + if (entry_data_list == NULL) { + return; + } + data_pool_destroy(entry_data_list->pool); +} + +void MMDB_close(MMDB_s *const mmdb) +{ + free_mmdb_struct(mmdb); +} + +LOCAL void free_mmdb_struct(MMDB_s *const mmdb) +{ + if (!mmdb) { + return; + } + + if (NULL != mmdb->filename) { + FREE_AND_SET_NULL(mmdb->filename); + } + if (NULL != mmdb->file_content) { +#ifdef _WIN32 + UnmapViewOfFile(mmdb->file_content); + /* Winsock is only initialized if open was successful so we only have + * to cleanup then. */ + WSACleanup(); +#else + munmap((void *)mmdb->file_content, mmdb->file_size); +#endif + } + + if (NULL != mmdb->metadata.database_type) { + FREE_AND_SET_NULL(mmdb->metadata.database_type); + } + + free_languages_metadata(mmdb); + free_descriptions_metadata(mmdb); +} + +LOCAL void free_languages_metadata(MMDB_s *mmdb) +{ + if (!mmdb->metadata.languages.names) { + return; + } + + for (size_t i = 0; i < mmdb->metadata.languages.count; i++) { + FREE_AND_SET_NULL(mmdb->metadata.languages.names[i]); + } + FREE_AND_SET_NULL(mmdb->metadata.languages.names); +} + +LOCAL void free_descriptions_metadata(MMDB_s *mmdb) +{ + if (!mmdb->metadata.description.count) { + return; + } + + for (size_t i = 0; i < mmdb->metadata.description.count; i++) { + if (NULL != mmdb->metadata.description.descriptions[i]) { + if (NULL != + mmdb->metadata.description.descriptions[i]->language) { + FREE_AND_SET_NULL( + mmdb->metadata.description.descriptions[i]->language); + } + + if (NULL != + mmdb->metadata.description.descriptions[i]->description) { + FREE_AND_SET_NULL( + mmdb->metadata.description.descriptions[i]->description); + } + FREE_AND_SET_NULL(mmdb->metadata.description.descriptions[i]); + } + } + + FREE_AND_SET_NULL(mmdb->metadata.description.descriptions); +} + +const char *MMDB_lib_version(void) +{ + return PACKAGE_VERSION; +} + +int MMDB_dump_entry_data_list(FILE *const stream, + MMDB_entry_data_list_s *const entry_data_list, + int indent) +{ + int status; + dump_entry_data_list(stream, entry_data_list, indent, &status); + return status; +} + +LOCAL MMDB_entry_data_list_s *dump_entry_data_list( + FILE *stream, MMDB_entry_data_list_s *entry_data_list, int indent, + int *status) +{ + switch (entry_data_list->entry_data.type) { + case MMDB_DATA_TYPE_MAP: + { + uint32_t size = entry_data_list->entry_data.data_size; + + print_indentation(stream, indent); + fprintf(stream, "{\n"); + indent += 2; + + for (entry_data_list = entry_data_list->next; + size && entry_data_list; size--) { + + if (MMDB_DATA_TYPE_UTF8_STRING != + entry_data_list->entry_data.type) { + *status = MMDB_INVALID_DATA_ERROR; + return NULL; + } + char *key = + mmdb_strndup( + (char *)entry_data_list->entry_data.utf8_string, + entry_data_list->entry_data.data_size); + if (NULL == key) { + *status = MMDB_OUT_OF_MEMORY_ERROR; + return NULL; + } + + print_indentation(stream, indent); + fprintf(stream, "\"%s\": \n", key); + free(key); + + entry_data_list = entry_data_list->next; + entry_data_list = + dump_entry_data_list(stream, entry_data_list, indent + 2, + status); + + if (MMDB_SUCCESS != *status) { + return NULL; + } + } + + indent -= 2; + print_indentation(stream, indent); + fprintf(stream, "}\n"); + } + break; + case MMDB_DATA_TYPE_ARRAY: + { + uint32_t size = entry_data_list->entry_data.data_size; + + print_indentation(stream, indent); + fprintf(stream, "[\n"); + indent += 2; + + for (entry_data_list = entry_data_list->next; + size && entry_data_list; size--) { + entry_data_list = + dump_entry_data_list(stream, entry_data_list, indent, + status); + if (MMDB_SUCCESS != *status) { + return NULL; + } + } + + indent -= 2; + print_indentation(stream, indent); + fprintf(stream, "]\n"); + } + break; + case MMDB_DATA_TYPE_UTF8_STRING: + { + char *string = + mmdb_strndup((char *)entry_data_list->entry_data.utf8_string, + entry_data_list->entry_data.data_size); + if (NULL == string) { + *status = MMDB_OUT_OF_MEMORY_ERROR; + return NULL; + } + print_indentation(stream, indent); + fprintf(stream, "\"%s\" <utf8_string>\n", string); + free(string); + entry_data_list = entry_data_list->next; + } + break; + case MMDB_DATA_TYPE_BYTES: + { + char *hex_string = + bytes_to_hex((uint8_t *)entry_data_list->entry_data.bytes, + entry_data_list->entry_data.data_size); + if (NULL == hex_string) { + *status = MMDB_OUT_OF_MEMORY_ERROR; + return NULL; + } + + print_indentation(stream, indent); + fprintf(stream, "%s <bytes>\n", hex_string); + free(hex_string); + + entry_data_list = entry_data_list->next; + } + break; + case MMDB_DATA_TYPE_DOUBLE: + print_indentation(stream, indent); + fprintf(stream, "%f <double>\n", + entry_data_list->entry_data.double_value); + entry_data_list = entry_data_list->next; + break; + case MMDB_DATA_TYPE_FLOAT: + print_indentation(stream, indent); + fprintf(stream, "%f <float>\n", + entry_data_list->entry_data.float_value); + entry_data_list = entry_data_list->next; + break; + case MMDB_DATA_TYPE_UINT16: + print_indentation(stream, indent); + fprintf(stream, "%u <uint16>\n", entry_data_list->entry_data.uint16); + entry_data_list = entry_data_list->next; + break; + case MMDB_DATA_TYPE_UINT32: + print_indentation(stream, indent); + fprintf(stream, "%u <uint32>\n", entry_data_list->entry_data.uint32); + entry_data_list = entry_data_list->next; + break; + case MMDB_DATA_TYPE_BOOLEAN: + print_indentation(stream, indent); + fprintf(stream, "%s <boolean>\n", + entry_data_list->entry_data.boolean ? "true" : "false"); + entry_data_list = entry_data_list->next; + break; + case MMDB_DATA_TYPE_UINT64: + print_indentation(stream, indent); + fprintf(stream, "%" PRIu64 " <uint64>\n", + entry_data_list->entry_data.uint64); + entry_data_list = entry_data_list->next; + break; + case MMDB_DATA_TYPE_UINT128: + print_indentation(stream, indent); +#if MMDB_UINT128_IS_BYTE_ARRAY + char *hex_string = + bytes_to_hex((uint8_t *)entry_data_list->entry_data.uint128, 16); + if (NULL == hex_string) { + *status = MMDB_OUT_OF_MEMORY_ERROR; + return NULL; + } + fprintf(stream, "0x%s <uint128>\n", hex_string); + free(hex_string); +#else + uint64_t high = entry_data_list->entry_data.uint128 >> 64; + uint64_t low = (uint64_t)entry_data_list->entry_data.uint128; + fprintf(stream, "0x%016" PRIX64 "%016" PRIX64 " <uint128>\n", high, + low); +#endif + entry_data_list = entry_data_list->next; + break; + case MMDB_DATA_TYPE_INT32: + print_indentation(stream, indent); + fprintf(stream, "%d <int32>\n", entry_data_list->entry_data.int32); + entry_data_list = entry_data_list->next; + break; + default: + *status = MMDB_INVALID_DATA_ERROR; + return NULL; + } + + *status = MMDB_SUCCESS; + return entry_data_list; +} + +LOCAL void print_indentation(FILE *stream, int i) +{ + char buffer[1024]; + int size = i >= 1024 ? 1023 : i; + memset(buffer, 32, size); + buffer[size] = '\0'; + fputs(buffer, stream); +} + +LOCAL char *bytes_to_hex(uint8_t *bytes, uint32_t size) +{ + char *hex_string; + MAYBE_CHECK_SIZE_OVERFLOW(size, SIZE_MAX / 2 - 1, NULL); + + hex_string = malloc((size * 2) + 1); + if (NULL == hex_string) { + return NULL; + } + + for (uint32_t i = 0; i < size; i++) { + sprintf(hex_string + (2 * i), "%02X", bytes[i]); + } + + return hex_string; +} + +const char *MMDB_strerror(int error_code) +{ + switch (error_code) { + case MMDB_SUCCESS: + return "Success (not an error)"; + case MMDB_FILE_OPEN_ERROR: + return "Error opening the specified MaxMind DB file"; + case MMDB_CORRUPT_SEARCH_TREE_ERROR: + return "The MaxMind DB file's search tree is corrupt"; + case MMDB_INVALID_METADATA_ERROR: + return "The MaxMind DB file contains invalid metadata"; + case MMDB_IO_ERROR: + return "An attempt to read data from the MaxMind DB file failed"; + case MMDB_OUT_OF_MEMORY_ERROR: + return "A memory allocation call failed"; + case MMDB_UNKNOWN_DATABASE_FORMAT_ERROR: + return + "The MaxMind DB file is in a format this library can't handle (unknown record size or binary format version)"; + case MMDB_INVALID_DATA_ERROR: + return + "The MaxMind DB file's data section contains bad data (unknown data type or corrupt data)"; + case MMDB_INVALID_LOOKUP_PATH_ERROR: + return + "The lookup path contained an invalid value (like a negative integer for an array index)"; + case MMDB_LOOKUP_PATH_DOES_NOT_MATCH_DATA_ERROR: + return + "The lookup path does not match the data (key that doesn't exist, array index bigger than the array, expected array or map where none exists)"; + case MMDB_INVALID_NODE_NUMBER_ERROR: + return + "The MMDB_read_node function was called with a node number that does not exist in the search tree"; + case MMDB_IPV6_LOOKUP_IN_IPV4_DATABASE_ERROR: + return + "You attempted to look up an IPv6 address in an IPv4-only database"; + default: + return "Unknown error code"; + } +} diff --git a/modules/net/srv/libmaxminddb/maxminddb.h b/modules/net/srv/libmaxminddb/maxminddb.h new file mode 100644 index 0000000000000000000000000000000000000000..f4b9bd24e48584ab6431775ec497e763bc4442f1 --- /dev/null +++ b/modules/net/srv/libmaxminddb/maxminddb.h @@ -0,0 +1,255 @@ +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef MAXMINDDB_H +#define MAXMINDDB_H + +/* Request POSIX.1-2008. However, we want to remain compatible with + * POSIX.1-2001 (since we have been historically and see no reason to drop + * compatibility). By requesting POSIX.1-2008, we can conditionally use + * features provided by that standard if the implementation provides it. We can + * check for what the implementation provides by checking the _POSIX_VERSION + * macro after including unistd.h. If a feature is in POSIX.1-2008 but not + * POSIX.1-2001, check that macro before using the feature (or check for the + * feature directly if possible). */ +#ifndef _POSIX_C_SOURCE +#define _POSIX_C_SOURCE 200809L +#endif + +#include "maxminddb_config.h" +#include <stdarg.h> +#include <stdbool.h> +#include <stdint.h> +#include <stdio.h> +#include <sys/types.h> + +#ifdef _WIN32 +#include <winsock2.h> +#include <ws2tcpip.h> +/* libmaxminddb package version from configure */ +#define PACKAGE_VERSION "1.4.2" + +typedef ADDRESS_FAMILY sa_family_t; + +#if defined(_MSC_VER) +/* MSVC doesn't define signed size_t, copy it from configure */ +#define ssize_t SSIZE_T + +/* MSVC doesn't support restricted pointers */ +#define restrict +#endif +#else +#include <netdb.h> +#include <netinet/in.h> +#include <sys/socket.h> +#endif + +#define MMDB_DATA_TYPE_EXTENDED (0) +#define MMDB_DATA_TYPE_POINTER (1) +#define MMDB_DATA_TYPE_UTF8_STRING (2) +#define MMDB_DATA_TYPE_DOUBLE (3) +#define MMDB_DATA_TYPE_BYTES (4) +#define MMDB_DATA_TYPE_UINT16 (5) +#define MMDB_DATA_TYPE_UINT32 (6) +#define MMDB_DATA_TYPE_MAP (7) +#define MMDB_DATA_TYPE_INT32 (8) +#define MMDB_DATA_TYPE_UINT64 (9) +#define MMDB_DATA_TYPE_UINT128 (10) +#define MMDB_DATA_TYPE_ARRAY (11) +#define MMDB_DATA_TYPE_CONTAINER (12) +#define MMDB_DATA_TYPE_END_MARKER (13) +#define MMDB_DATA_TYPE_BOOLEAN (14) +#define MMDB_DATA_TYPE_FLOAT (15) + +#define MMDB_RECORD_TYPE_SEARCH_NODE (0) +#define MMDB_RECORD_TYPE_EMPTY (1) +#define MMDB_RECORD_TYPE_DATA (2) +#define MMDB_RECORD_TYPE_INVALID (3) + +/* flags for open */ +#define MMDB_MODE_MMAP (1) +#define MMDB_MODE_MASK (7) + +/* error codes */ +#define MMDB_SUCCESS (0) +#define MMDB_FILE_OPEN_ERROR (1) +#define MMDB_CORRUPT_SEARCH_TREE_ERROR (2) +#define MMDB_INVALID_METADATA_ERROR (3) +#define MMDB_IO_ERROR (4) +#define MMDB_OUT_OF_MEMORY_ERROR (5) +#define MMDB_UNKNOWN_DATABASE_FORMAT_ERROR (6) +#define MMDB_INVALID_DATA_ERROR (7) +#define MMDB_INVALID_LOOKUP_PATH_ERROR (8) +#define MMDB_LOOKUP_PATH_DOES_NOT_MATCH_DATA_ERROR (9) +#define MMDB_INVALID_NODE_NUMBER_ERROR (10) +#define MMDB_IPV6_LOOKUP_IN_IPV4_DATABASE_ERROR (11) + +#if !(MMDB_UINT128_IS_BYTE_ARRAY) +#if MMDB_UINT128_USING_MODE +typedef unsigned int mmdb_uint128_t __attribute__ ((__mode__(TI))); +#else +typedef unsigned __int128 mmdb_uint128_t; +#endif +#endif + +/* This is a pointer into the data section for a given IP address lookup */ +typedef struct MMDB_entry_s { + const struct MMDB_s *mmdb; + uint32_t offset; +} MMDB_entry_s; + +typedef struct MMDB_lookup_result_s { + bool found_entry; + MMDB_entry_s entry; + uint16_t netmask; +} MMDB_lookup_result_s; + +typedef struct MMDB_entry_data_s { + bool has_data; + union { + uint32_t pointer; + const char *utf8_string; + double double_value; + const uint8_t *bytes; + uint16_t uint16; + uint32_t uint32; + int32_t int32; + uint64_t uint64; +#if MMDB_UINT128_IS_BYTE_ARRAY + uint8_t uint128[16]; +#else + mmdb_uint128_t uint128; +#endif + bool boolean; + float float_value; + }; + /* This is a 0 if a given entry cannot be found. This can only happen + * when a call to MMDB_(v)get_value() asks for hash keys or array + * indices that don't exist. */ + uint32_t offset; + /* This is the next entry in the data section, but it's really only + * relevant for entries that part of a larger map or array + * struct. There's no good reason for an end user to look at this + * directly. */ + uint32_t offset_to_next; + /* This is only valid for strings, utf8_strings or binary data */ + uint32_t data_size; + /* This is an MMDB_DATA_TYPE_* constant */ + uint32_t type; +} MMDB_entry_data_s; + +/* This is the return type when someone asks for all the entry data in a map or array */ +typedef struct MMDB_entry_data_list_s { + MMDB_entry_data_s entry_data; + struct MMDB_entry_data_list_s *next; + void *pool; +} MMDB_entry_data_list_s; + +typedef struct MMDB_description_s { + const char *language; + const char *description; +} MMDB_description_s; + +/* WARNING: do not add new fields to this struct without bumping the SONAME. + * The struct is allocated by the users of this library and increasing the + * size will cause existing users to allocate too little space when the shared + * library is upgraded */ +typedef struct MMDB_metadata_s { + uint32_t node_count; + uint16_t record_size; + uint16_t ip_version; + const char *database_type; + struct { + size_t count; + const char **names; + } languages; + uint16_t binary_format_major_version; + uint16_t binary_format_minor_version; + uint64_t build_epoch; + struct { + size_t count; + MMDB_description_s **descriptions; + } description; + /* See above warning before adding fields */ +} MMDB_metadata_s; + +/* WARNING: do not add new fields to this struct without bumping the SONAME. + * The struct is allocated by the users of this library and increasing the + * size will cause existing users to allocate too little space when the shared + * library is upgraded */ +typedef struct MMDB_ipv4_start_node_s { + uint16_t netmask; + uint32_t node_value; + /* See above warning before adding fields */ +} MMDB_ipv4_start_node_s; + +/* WARNING: do not add new fields to this struct without bumping the SONAME. + * The struct is allocated by the users of this library and increasing the + * size will cause existing users to allocate too little space when the shared + * library is upgraded */ +typedef struct MMDB_s { + uint32_t flags; + const char *filename; + ssize_t file_size; + const uint8_t *file_content; + const uint8_t *data_section; + uint32_t data_section_size; + const uint8_t *metadata_section; + uint32_t metadata_section_size; + uint16_t full_record_byte_size; + uint16_t depth; + MMDB_ipv4_start_node_s ipv4_start_node; + MMDB_metadata_s metadata; + /* See above warning before adding fields */ +} MMDB_s; + +typedef struct MMDB_search_node_s { + uint64_t left_record; + uint64_t right_record; + uint8_t left_record_type; + uint8_t right_record_type; + MMDB_entry_s left_record_entry; + MMDB_entry_s right_record_entry; +} MMDB_search_node_s; + +extern int MMDB_open(const char *const filename, uint32_t flags, + MMDB_s *const mmdb); +extern MMDB_lookup_result_s MMDB_lookup_string(const MMDB_s *const mmdb, + const char *const ipstr, + int *const gai_error, + int *const mmdb_error); +extern MMDB_lookup_result_s MMDB_lookup_sockaddr( + const MMDB_s *const mmdb, + const struct sockaddr *const sockaddr, + int *const mmdb_error); +extern int MMDB_read_node(const MMDB_s *const mmdb, + uint32_t node_number, + MMDB_search_node_s *const node); +extern int MMDB_get_value(MMDB_entry_s *const start, + MMDB_entry_data_s *const entry_data, + ...); +extern int MMDB_vget_value(MMDB_entry_s *const start, + MMDB_entry_data_s *const entry_data, + va_list va_path); +extern int MMDB_aget_value(MMDB_entry_s *const start, + MMDB_entry_data_s *const entry_data, + const char *const *const path); +extern int MMDB_get_metadata_as_entry_data_list( + const MMDB_s *const mmdb, MMDB_entry_data_list_s **const entry_data_list); +extern int MMDB_get_entry_data_list( + MMDB_entry_s *start, MMDB_entry_data_list_s **const entry_data_list); +extern void MMDB_free_entry_data_list( + MMDB_entry_data_list_s *const entry_data_list); +extern void MMDB_close(MMDB_s *const mmdb); +extern const char *MMDB_lib_version(void); +extern int MMDB_dump_entry_data_list(FILE *const stream, + MMDB_entry_data_list_s *const entry_data_list, + int indent); +extern const char *MMDB_strerror(int error_code); + +#endif /* MAXMINDDB_H */ + +#ifdef __cplusplus +} +#endif diff --git a/modules/net/srv/libmaxminddb/maxminddb_config.h b/modules/net/srv/libmaxminddb/maxminddb_config.h new file mode 100644 index 0000000000000000000000000000000000000000..0b824ee8272b4a4cc2eebdf0a507249f8f93414c --- /dev/null +++ b/modules/net/srv/libmaxminddb/maxminddb_config.h @@ -0,0 +1,18 @@ +#ifndef MAXMINDDB_CONFIG_H +#define MAXMINDDB_CONFIG_H + +/* libmaxminddb package version from configure */ +#define PACKAGE_VERSION "1.4.2" + +#ifndef MMDB_UINT128_USING_MODE +/* Define as 1 if we we use unsigned int __atribute__ ((__mode__(TI))) for uint128 values */ +#define MMDB_UINT128_USING_MODE 0 +#endif + +#ifndef MMDB_UINT128_IS_BYTE_ARRAY +/* Define as 1 if we don't have an unsigned __int128 type */ +#define MMDB_UINT128_IS_BYTE_ARRAY 1 +#endif + +#endif /* MAXMINDDB_CONFIG_H */ + diff --git a/modules/net/srv/libmaxminddb/mmdblookup.c b/modules/net/srv/libmaxminddb/mmdblookup.c new file mode 100644 index 0000000000000000000000000000000000000000..4a3403c67e0f3466ea31d6a7ca856cd938d42758 --- /dev/null +++ b/modules/net/srv/libmaxminddb/mmdblookup.c @@ -0,0 +1,762 @@ +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include "maxminddb.h" +#include <errno.h> +#include <getopt.h> +#ifndef _WIN32 +#include <pthread.h> +#endif +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> + +#ifdef _WIN32 +#ifndef UNICODE +#define UNICODE +#endif +#include <malloc.h> +#else +#include <libgen.h> +#include <unistd.h> +#endif + +#define LOCAL static + +LOCAL void usage(char *program, int exit_code, const char *error); +LOCAL const char **get_options( + int argc, + char **argv, + char **mmdb_file, + char **ip_address, + int *verbose, + int *iterations, + int *lookup_path_length, + int *const thread_count, + char **const ip_file); +LOCAL MMDB_s open_or_die(const char *fname); +LOCAL void dump_meta(MMDB_s *mmdb); +LOCAL bool lookup_from_file(MMDB_s *const mmdb, + char const *const ip_file, + bool const dump); +LOCAL int lookup_and_print(MMDB_s *mmdb, const char *ip_address, + const char **lookup_path, + int lookup_path_length, + bool verbose); +LOCAL int benchmark(MMDB_s *mmdb, int iterations); +LOCAL MMDB_lookup_result_s lookup_or_die(MMDB_s *mmdb, const char *ipstr); +LOCAL void random_ipv4(char *ip); + +#ifndef _WIN32 +// These aren't with the automatically generated prototypes as we'd lose the +// enclosing macros. +static bool start_threaded_benchmark( + MMDB_s *const mmdb, + int const thread_count, + int const iterations); +static long double get_time(void); +static void *thread(void *arg); +#endif + +#ifdef _WIN32 +int wmain(int argc, wchar_t **wargv) +{ + // Convert our argument list from UTF-16 to UTF-8. + char **argv = (char **)malloc(argc * sizeof(char *)); + if (!argv) { + fprintf(stderr, "malloc(): %s\n", strerror(errno)); + exit(1); + } + for (int i = 0; i < argc; i++) { + int utf8_width; + char *utf8_string; + utf8_width = WideCharToMultiByte(CP_UTF8, 0, wargv[i], -1, NULL, 0, + NULL, NULL); + if (utf8_width < 1) { + fprintf(stderr, "WideCharToMultiByte() failed: %d\n", + GetLastError()); + exit(1); + } + utf8_string = malloc(utf8_width); + if (!utf8_string) { + fprintf(stderr, "malloc(): %s\n", strerror(errno)); + exit(1); + } + if (WideCharToMultiByte(CP_UTF8, 0, wargv[i], -1, utf8_string, + utf8_width, NULL, NULL) < 1) { + fprintf(stderr, "WideCharToMultiByte() failed: %d\n", + GetLastError()); + exit(1); + } + argv[i] = utf8_string; + } +#else // _WIN32 +int main(int argc, char **argv) +{ +#endif // _WIN32 + char *mmdb_file = NULL; + char *ip_address = NULL; + int verbose = 0; + int iterations = 0; + int lookup_path_length = 0; + int thread_count = 0; + char *ip_file = NULL; + + const char **lookup_path = + get_options(argc, argv, &mmdb_file, &ip_address, &verbose, &iterations, + &lookup_path_length, &thread_count, &ip_file); + + MMDB_s mmdb = open_or_die(mmdb_file); + + if (verbose) { + dump_meta(&mmdb); + } + + // The benchmarking and lookup from file modes are hidden features mainly + // intended for development right now. This means there are several flags + // that exist but are intentionally not mentioned in the usage or man page. + + // The lookup from file mode may be useful to expose publicly in the usage, + // but we should have it respect the lookup_path functionality if we do so. + if (ip_file) { + free((void *)lookup_path); + if (!lookup_from_file(&mmdb, ip_file, verbose == 1)) { + MMDB_close(&mmdb); + return 1; + } + MMDB_close(&mmdb); + return 0; + } + + if (0 == iterations) { + exit(lookup_and_print(&mmdb, ip_address, lookup_path, + lookup_path_length, verbose)); + } + + free((void *)lookup_path); + + srand( (int)time(NULL) ); + +#ifndef _WIN32 + if (thread_count > 0) { + if (!start_threaded_benchmark(&mmdb, thread_count, iterations)) { + MMDB_close(&mmdb); + exit(1); + } + MMDB_close(&mmdb); + exit(0); + } +#endif + + exit(benchmark(&mmdb, iterations)); +} + +LOCAL void usage(char *program, int exit_code, const char *error) +{ + if (NULL != error) { + fprintf(stderr, "\n *ERROR: %s\n", error); + } + + char *usage = "\n" + " %s --file /path/to/file.mmdb --ip 1.2.3.4 [path to lookup]\n" + "\n" + " This application accepts the following options:\n" + "\n" + " --file (-f) The path to the MMDB file. Required.\n" + "\n" + " --ip (-i) The IP address to look up. Required.\n" + "\n" + " --verbose (-v) Turns on verbose output. Specifically, this causes this\n" + " application to output the database metadata.\n" + "\n" + " --version Print the program's version number and exit.\n" + "\n" + " --help (-h -?) Show usage information.\n" + "\n" + " If an IP's data entry resolves to a map or array, you can provide\n" + " a lookup path to only show part of that data.\n" + "\n" + " For example, given a JSON structure like this:\n" + "\n" + " {\n" + " \"names\": {\n" + " \"en\": \"Germany\",\n" + " \"de\": \"Deutschland\"\n" + " },\n" + " \"cities\": [ \"Berlin\", \"Frankfurt\" ]\n" + " }\n" + "\n" + " You could look up just the English name by calling mmdblookup with a lookup path of:\n" + "\n" + " mmdblookup --file ... --ip ... names en\n" + "\n" + " Or you could look up the second city in the list with:\n" + "\n" + " mmdblookup --file ... --ip ... cities 1\n" + "\n" + " Array numbering begins with zero (0).\n" + "\n" + " If you do not provide a path to lookup, all of the information for a given IP\n" + " will be shown.\n" + "\n"; + + fprintf(stdout, usage, program); + exit(exit_code); +} + +LOCAL const char **get_options( + int argc, + char **argv, + char **mmdb_file, + char **ip_address, + int *verbose, + int *iterations, + int *lookup_path_length, + int *const thread_count, + char **const ip_file) +{ + static int help = 0; + static int version = 0; + + while (1) { + static struct option options[] = { + { "file", required_argument, 0, 'f' }, + { "ip", required_argument, 0, 'i' }, + { "verbose", no_argument, 0, 'v' }, + { "version", no_argument, 0, 'n' }, + { "benchmark", required_argument, 0, 'b' }, +#ifndef _WIN32 + { "threads", required_argument, 0, 't' }, +#endif + { "ip-file", required_argument, 0, 'I' }, + { "help", no_argument, 0, 'h' }, + { "?", no_argument, 0, 1 }, + { 0, 0, 0, 0 } + }; + + int opt_index; +#ifdef _WIN32 + char const * const optstring = "f:i:b:I:vnh?"; +#else + char const * const optstring = "f:i:b:t:I:vnh?"; +#endif + int opt_char = getopt_long(argc, argv, optstring, options, + &opt_index); + + if (-1 == opt_char) { + break; + } + + if ('f' == opt_char) { + *mmdb_file = optarg; + } else if ('i' == opt_char) { + *ip_address = optarg; + } else if ('v' == opt_char) { + *verbose = 1; + } else if ('n' == opt_char) { + version = 1; + } else if ('b' == opt_char) { + *iterations = strtol(optarg, NULL, 10); + } else if ('h' == opt_char || '?' == opt_char) { + help = 1; + } else if (opt_char == 't') { + *thread_count = strtol(optarg, NULL, 10); + } else if (opt_char == 'I') { + *ip_file = optarg; + } + } + +#ifdef _WIN32 + char *program = alloca(strlen(argv[0])); + _splitpath(argv[0], NULL, NULL, program, NULL); + _splitpath(argv[0], NULL, NULL, NULL, program + strlen(program)); +#else + char *program = basename(argv[0]); +#endif + + if (help) { + usage(program, 0, NULL); + } + + if (version) { + fprintf(stdout, "\n %s version %s\n\n", program, PACKAGE_VERSION); + exit(0); + } + + if (NULL == *mmdb_file) { + usage(program, 1, "You must provide a filename with --file"); + } + + if (*ip_address == NULL && *iterations == 0 && !*ip_file) { + usage(program, 1, "You must provide an IP address with --ip"); + } + + const char **lookup_path = + malloc(sizeof(const char *) * ((argc - optind) + 1)); + int i; + for (i = 0; i < argc - optind; i++) { + lookup_path[i] = argv[i + optind]; + (*lookup_path_length)++; + } + lookup_path[i] = NULL; + + return lookup_path; +} + +LOCAL MMDB_s open_or_die(const char *fname) +{ + MMDB_s mmdb; + int status = MMDB_open(fname, MMDB_MODE_MMAP, &mmdb); + + if (MMDB_SUCCESS != status) { + fprintf(stderr, "\n Can't open %s - %s\n", fname, + MMDB_strerror(status)); + + if (MMDB_IO_ERROR == status) { + fprintf(stderr, " IO error: %s\n", strerror(errno)); + } + + fprintf(stderr, "\n"); + + exit(2); + } + + return mmdb; +} + +LOCAL void dump_meta(MMDB_s *mmdb) +{ + const char *meta_dump = "\n" + " Database metadata\n" + " Node count: %i\n" + " Record size: %i bits\n" + " IP version: IPv%i\n" + " Binary format: %i.%i\n" + " Build epoch: %llu (%s)\n" + " Type: %s\n" + " Languages: "; + + char date[40]; + const time_t epoch = (const time_t)mmdb->metadata.build_epoch; + strftime(date, 40, "%F %T UTC", gmtime(&epoch)); + + fprintf(stdout, meta_dump, + mmdb->metadata.node_count, + mmdb->metadata.record_size, + mmdb->metadata.ip_version, + mmdb->metadata.binary_format_major_version, + mmdb->metadata.binary_format_minor_version, + mmdb->metadata.build_epoch, + date, + mmdb->metadata.database_type); + + for (size_t i = 0; i < mmdb->metadata.languages.count; i++) { + fprintf(stdout, "%s", mmdb->metadata.languages.names[i]); + if (i < mmdb->metadata.languages.count - 1) { + fprintf(stdout, " "); + } + } + fprintf(stdout, "\n"); + + fprintf(stdout, " Description:\n"); + for (size_t i = 0; i < mmdb->metadata.description.count; i++) { + fprintf(stdout, " %s: %s\n", + mmdb->metadata.description.descriptions[i]->language, + mmdb->metadata.description.descriptions[i]->description); + } + fprintf(stdout, "\n"); +} + +// The input file should have one IP per line. +// +// We look up each IP. +// +// If dump is true, we dump the data for each IP to stderr. This is useful for +// comparison in that you can dump out the data for the IPs before and after +// making changes. It goes to stderr rather than stdout so that the report does +// not get included in what you will compare (since it will almost always be +// different). +// +// In addition to being useful for comparisons, this function provides a way to +// have a more deterministic set of lookups for benchmarking. +LOCAL bool lookup_from_file(MMDB_s *const mmdb, + char const *const ip_file, + bool const dump) +{ + FILE *const fh = fopen(ip_file, "r"); + if (!fh) { + fprintf(stderr, "fopen(): %s: %s\n", ip_file, strerror(errno)); + return false; + } + + clock_t const clock_start = clock(); + char buf[1024] = { 0 }; + // I'd normally use uint64_t, but support for it is optional in C99. + unsigned long long i = 0; + while (1) { + if (fgets(buf, sizeof(buf), fh) == NULL) { + if (!feof(fh)) { + fprintf(stderr, "fgets(): %s\n", strerror(errno)); + fclose(fh); + return false; + } + if (fclose(fh) != 0) { + fprintf(stderr, "fclose(): %s\n", strerror(errno)); + return false; + } + break; + } + + char *ptr = buf; + while (*ptr != '\0') { + if (*ptr == '\n') { + *ptr = '\0'; + break; + } + ptr++; + } + if (strlen(buf) == 0) { + continue; + } + + i++; + + MMDB_lookup_result_s result = lookup_or_die(mmdb, buf); + if (!result.found_entry) { + continue; + } + + MMDB_entry_data_list_s *entry_data_list = NULL; + int const status = MMDB_get_entry_data_list(&result.entry, + &entry_data_list); + if (status != MMDB_SUCCESS) { + fprintf(stderr, "MMDB_get_entry_data_list(): %s\n", + MMDB_strerror(status)); + fclose(fh); + MMDB_free_entry_data_list(entry_data_list); + return false; + } + + if (!entry_data_list) { + fprintf(stderr, "entry_data_list is NULL\n"); + fclose(fh); + return false; + } + + if (dump) { + fprintf(stdout, "%s:\n", buf); + int const status = MMDB_dump_entry_data_list(stderr, + entry_data_list, 0); + if (status != MMDB_SUCCESS) { + fprintf(stderr, "MMDB_dump_entry_data_list(): %s\n", + MMDB_strerror(status)); + fclose(fh); + MMDB_free_entry_data_list(entry_data_list); + return false; + } + } + + MMDB_free_entry_data_list(entry_data_list); + } + + clock_t const clock_diff = clock() - clock_start; + double const seconds = (double)clock_diff / CLOCKS_PER_SEC; + + fprintf( + stdout, + "Looked up %llu addresses in %.2f seconds. %.2f lookups per second.\n", + i, seconds, i / seconds); + + return true; +} + +LOCAL int lookup_and_print(MMDB_s *mmdb, const char *ip_address, + const char **lookup_path, + int lookup_path_length, + bool verbose) +{ + + MMDB_lookup_result_s result = lookup_or_die(mmdb, ip_address); + MMDB_entry_data_list_s *entry_data_list = NULL; + + int exit_code = 0; + + if (verbose) { + fprintf( + stdout, + "\n Record prefix length: %d\n", + result.netmask + ); + } + + if (result.found_entry) { + int status; + if (lookup_path_length) { + MMDB_entry_data_s entry_data; + status = MMDB_aget_value(&result.entry, &entry_data, + lookup_path); + if (MMDB_SUCCESS == status) { + if (entry_data.offset) { + MMDB_entry_s entry = + { .mmdb = mmdb, .offset = entry_data.offset }; + status = MMDB_get_entry_data_list(&entry, + &entry_data_list); + } else { + fprintf( + stdout, + "\n No data was found at the lookup path you provided\n\n"); + } + } + } else { + status = MMDB_get_entry_data_list(&result.entry, + &entry_data_list); + } + + if (MMDB_SUCCESS != status) { + fprintf(stderr, "Got an error looking up the entry data - %s\n", + MMDB_strerror(status)); + exit_code = 5; + goto end; + } + + if (NULL != entry_data_list) { + fprintf(stdout, "\n"); + MMDB_dump_entry_data_list(stdout, entry_data_list, 2); + fprintf(stdout, "\n"); + } + } else { + fprintf(stderr, + "\n Could not find an entry for this IP address (%s)\n\n", + ip_address); + exit_code = 6; + } + + end: + MMDB_free_entry_data_list(entry_data_list); + MMDB_close(mmdb); + free((void *)lookup_path); + + return exit_code; +} + +LOCAL int benchmark(MMDB_s *mmdb, int iterations) +{ + char ip_address[16]; + int exit_code = 0; + + clock_t time = clock(); + + for (int i = 0; i < iterations; i++) { + random_ipv4(ip_address); + + MMDB_lookup_result_s result = lookup_or_die(mmdb, ip_address); + MMDB_entry_data_list_s *entry_data_list = NULL; + + if (result.found_entry) { + + int status = MMDB_get_entry_data_list(&result.entry, + &entry_data_list); + + if (MMDB_SUCCESS != status) { + fprintf(stderr, "Got an error looking up the entry data - %s\n", + MMDB_strerror(status)); + exit_code = 5; + MMDB_free_entry_data_list(entry_data_list); + goto end; + } + } + + MMDB_free_entry_data_list(entry_data_list); + } + + time = clock() - time; + double seconds = ((double)time / CLOCKS_PER_SEC); + fprintf( + stdout, + "\n Looked up %i addresses in %.2f seconds. %.2f lookups per second.\n\n", + iterations, seconds, iterations / seconds); + + end: + MMDB_close(mmdb); + + return exit_code; +} + +LOCAL MMDB_lookup_result_s lookup_or_die(MMDB_s *mmdb, const char *ipstr) +{ + int gai_error, mmdb_error; + MMDB_lookup_result_s result = + MMDB_lookup_string(mmdb, ipstr, &gai_error, &mmdb_error); + + if (0 != gai_error) { + fprintf(stderr, + "\n Error from call to getaddrinfo for %s - %s\n\n", + ipstr, +#ifdef _WIN32 + gai_strerrorA(gai_error) +#else + gai_strerror(gai_error) +#endif + ); + exit(3); + } + + if (MMDB_SUCCESS != mmdb_error) { + fprintf(stderr, "\n Got an error from the maxminddb library: %s\n\n", + MMDB_strerror(mmdb_error)); + exit(4); + } + + return result; +} + +LOCAL void random_ipv4(char *ip) +{ + // rand() is perfectly fine for this use case + // coverity[dont_call] + int ip_int = rand(); + uint8_t *bytes = (uint8_t *)&ip_int; + + snprintf(ip, 16, "%u.%u.%u.%u", + *bytes, *(bytes + 1), *(bytes + 2), *(bytes + 3)); +} + +#ifndef _WIN32 +struct thread_info { + pthread_t id; + int num; + MMDB_s *mmdb; + int iterations; +}; + +static bool start_threaded_benchmark( + MMDB_s *const mmdb, + int const thread_count, + int const iterations) +{ + struct thread_info *const tinfo = calloc(thread_count, + sizeof(struct thread_info)); + if (!tinfo) { + fprintf(stderr, "calloc(): %s\n", strerror(errno)); + return false; + } + + // Using clock() isn't appropriate for multiple threads. It's CPU time, not + // wall time. + long double const start_time = get_time(); + if (start_time == -1) { + free(tinfo); + return false; + } + + for (int i = 0; i < thread_count; i++) { + tinfo[i].num = i; + tinfo[i].mmdb = mmdb; + tinfo[i].iterations = iterations; + + if (pthread_create(&tinfo[i].id, NULL, &thread, &tinfo[i]) != 0) { + fprintf(stderr, "pthread_create() failed\n"); + free(tinfo); + return false; + } + } + + for (int i = 0; i < thread_count; i++) { + if (pthread_join(tinfo[i].id, NULL) != 0) { + fprintf(stderr, "pthread_join() failed\n"); + free(tinfo); + return false; + } + } + + free(tinfo); + + long double const end_time = get_time(); + if (end_time == -1) { + return false; + } + + long double const elapsed = end_time - start_time; + unsigned long long const total_ips = iterations * thread_count; + long double rate = total_ips; + if (elapsed != 0) { + rate = total_ips / elapsed; + } + + fprintf( + stdout, + "Looked up %llu addresses using %d threads in %.2Lf seconds. %.2Lf lookups per second.\n", + total_ips, thread_count, elapsed, rate); + + return true; +} + +static long double get_time(void) +{ + // clock_gettime() is not present on OSX until 10.12. +#ifdef HAVE_CLOCK_GETTIME + struct timespec tp = { + .tv_sec = 0, + .tv_nsec = 0, + }; + clockid_t clk_id = CLOCK_REALTIME; +#ifdef _POSIX_MONOTONIC_CLOCK + clk_id = CLOCK_MONOTONIC; +#endif + if (clock_gettime(clk_id, &tp) != 0) { + fprintf(stderr, "clock_gettime(): %s\n", strerror(errno)); + return -1; + } + return tp.tv_sec + ((float)tp.tv_nsec / 1e9); +#else + time_t t = time(NULL); + if (t == (time_t)-1) { + fprintf(stderr, "time(): %s\n", strerror(errno)); + return -1; + } + return (long double)t; +#endif +} + +static void *thread(void *arg) +{ + const struct thread_info *const tinfo = arg; + if (!tinfo) { + fprintf(stderr, "thread(): %s\n", strerror(EINVAL)); + return NULL; + } + + char ip_address[16] = { 0 }; + + for (int i = 0; i < tinfo->iterations; i++) { + memset(ip_address, 0, 16); + random_ipv4(ip_address); + + MMDB_lookup_result_s result = lookup_or_die(tinfo->mmdb, ip_address); + if (!result.found_entry) { + continue; + } + + MMDB_entry_data_list_s *entry_data_list = NULL; + int const status = MMDB_get_entry_data_list(&result.entry, + &entry_data_list); + if (status != MMDB_SUCCESS) { + fprintf(stderr, "MMDB_get_entry_data_list(): %s\n", + MMDB_strerror(status)); + MMDB_free_entry_data_list(entry_data_list); + return NULL; + } + + if (!entry_data_list) { + fprintf(stderr, "entry_data_list is NULL\n"); + return NULL; + } + + MMDB_free_entry_data_list(entry_data_list); + } + + return NULL; +} +#endif diff --git a/modules/service/vpn/dap_chain_net_srv_vpn_cdb_server_list.c b/modules/service/vpn/dap_chain_net_srv_vpn_cdb_server_list.c index 571383aba425ba26a6097826dca39a1b6f73f2c1..e3c807118e9ea489ea2f5c3322bc8247b76f6778 100644 --- a/modules/service/vpn/dap_chain_net_srv_vpn_cdb_server_list.c +++ b/modules/service/vpn/dap_chain_net_srv_vpn_cdb_server_list.c @@ -27,6 +27,7 @@ #include <time.h> #include <stdio.h> #include <stdlib.h> +#include <stdint.h> #include <string.h> #include <unistd.h> @@ -43,6 +44,7 @@ #include "dap_chain_net_srv.h" #include "dap_chain_net_srv_vpn.h" #include "dap_chain_net_srv_order.h" +#include "dap_chain_net_srv_geoip.h" #include "dap_http.h" #include "dap_http_simple.h" @@ -154,6 +156,9 @@ static void s_http_simple_proc(dap_http_simple_t *a_http_simple, void *a_arg) dap_string_t *l_reply_str = dap_string_new("[\n"); + char *l_client_ip = a_http_simple->http->client->s_ip;//"77.222.110.44" + geoip_info_t *l_geoip_info = chain_net_geoip_get_ip_info(l_client_ip); + log_it(L_DEBUG, "Have %zd chain networks for cdb lists", s_cdb_net_count ); for ( size_t i = 0; i < s_cdb_net_count ; i++ ) { @@ -225,21 +230,47 @@ static void s_http_simple_proc(dap_http_simple_t *a_http_simple, void *a_arg) } } - // random node - int l_count = 0; - while(l_orders_num > 0) { - // first random node - size_t k = rand() % l_orders_num; - dap_chain_net_srv_order_t *l_order = l_orders_pos[k]; - if(!order_info_print(l_reply_str, l_net, l_order, "Auto", -1)){ - dap_string_append_printf(l_reply_str, ",\n"); - break; - } - if (l_count>20) - break; - l_count++; + int8_t l_client_continent = l_geoip_info ? dap_chain_net_srv_order_continent_to_num(l_geoip_info->continent) : 0; + // random node on client's continent + if (l_client_continent) { + int l_count = 0; + while (l_orders_num > 0) { + size_t k = rand() % l_continents_numbers[l_client_continent]; + dap_chain_net_srv_order_t *l_order = l_orders_pos[k]; + const char *country_code = dap_chain_net_srv_order_get_country_code(l_order); + if (country_code) { + // only for other countries + if (dap_strcmp(l_geoip_info->country_code, country_code)){ + if (!order_info_print(l_reply_str, l_net, l_order, "Auto", -1)) { + dap_string_append_printf(l_reply_str, ",\n"); + break; + } + } + } + if (l_count > 20) + break; + l_count++; + } + + } + // random node for the whole world + else { + int l_count = 0; + while(l_orders_num > 0) { + // first random node + size_t k = rand() % l_orders_num; + dap_chain_net_srv_order_t *l_order = l_orders_pos[k]; + if(!order_info_print(l_reply_str, l_net, l_order, "Auto", -1)){ + dap_string_append_printf(l_reply_str, ",\n"); + break; + } + if (l_count>20) + break; + l_count++; + } } // random nodes for continents + int l_count = 0; for(size_t l_c = 0; l_c < l_continents_count; l_c++) { while(l_continents_numbers[l_c] > 0) { // random node for continent @@ -290,6 +321,7 @@ static void s_http_simple_proc(dap_http_simple_t *a_http_simple, void *a_arg) } } } + DAP_DELETE(l_geoip_info); dap_string_append_printf( l_reply_str, "]\n\n"); dap_http_simple_reply( a_http_simple, l_reply_str->str, l_reply_str->len ); dap_string_free(l_reply_str, true);